1 /*
2 Copyright (C) 1998 T. Scott Dattalo
3
4 This file is part of the libgpsim library of gpsim
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20
21
22 #include <assert.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <iostream>
27 #include <iomanip>
28
29 #include "cmd_manager.h"
30 #include "../config.h"
31 #include "pic-processor.h"
32 #include "breakpoints.h"
33 #include "14bit-processors.h"
34 #include "14bit-registers.h"
35 #include "expr.h"
36 #include "gpsim_interface.h"
37 #include "gpsim_time.h"
38 #include "modules.h"
39 #include "operator.h"
40 #include "processor.h"
41 #include "trace.h"
42 #include "ui.h"
43 #include "value.h"
44
45 #include "icd.h"
46
47 #define PCPU ((Processor *)cpu)
48
49 extern guint64 simulation_start_cycle;
50
51 // Global declaration of THE breakpoint object
52 // create an instance of inline get_trace() method by taking its address
53 Breakpoints &(*dummy_bp)() = get_bp;
54 Breakpoints bp;
55
56
57 //------------------------------------------------------------------------
58 // find_free - search the array that holds the break points for a free slot
59 //
find_free()60 int Breakpoints::find_free()
61 {
62 for (int i = 0; i < MAX_BREAKPOINTS; i++) {
63 if (break_status[i].type == BREAK_CLEAR) {
64 if (i + 1 > m_iMaxAllocated) {
65 m_iMaxAllocated = i + 1;
66 }
67
68 return i;
69 }
70 }
71
72 std::cout << "*** out of breakpoints\n";
73 return MAX_BREAKPOINTS;
74 }
75
76
77 //------------------------------------------------------------------------
78 // set_breakpoint - Set a breakpoint of a specific type.
79 //
set_breakpoint(BREAKPOINT_TYPES break_type,Processor * cpu,unsigned int arg1,unsigned arg2,TriggerObject * f1)80 int Breakpoints::set_breakpoint(BREAKPOINT_TYPES break_type,
81 Processor *cpu,
82 unsigned int arg1,
83 unsigned arg2,
84 TriggerObject *f1)
85 {
86 breakpoint_number = find_free();
87
88 if (breakpoint_number >= MAX_BREAKPOINTS) {
89 return breakpoint_number;
90 }
91
92 BreakStatus &bs = break_status[breakpoint_number];
93 bs.type = break_type;
94 bs.cpu = cpu;
95 bs.arg1 = arg1;
96 bs.arg2 = arg2;
97 bs.bpo = f1;
98
99 switch (break_type) {
100 case BREAK_ON_INVALID_FR:
101 return (breakpoint_number);
102 break;
103
104 case BREAK_ON_CYCLE: {
105 guint64 cyc = arg2;
106 cyc = (cyc << 32) | arg1;
107
108 // The cycle counter does its own break points.
109 if (get_cycles().set_break(cyc, f1, breakpoint_number)) {
110 if (cpu != nullptr) {
111 cpu->NotifyBreakpointSet(bs, f1);
112 }
113
114 return breakpoint_number;
115
116 } else {
117 bs.type = BREAK_CLEAR;
118 }
119 }
120 break;
121
122 case BREAK_ON_STK_OVERFLOW:
123 if ((cpu->GetCapabilities() & Processor::eBREAKONSTACKOVER)
124 == Processor::eBREAKONSTACKOVER) {
125 // pic_processor should not be referenced here
126 // Should have a GetStack() virtual function in Processor class.
127 // Of course then the Stack class needs to be a virtual class.
128 if (((pic_processor *)(cpu))->stack->set_break_on_overflow(1)) {
129 return breakpoint_number;
130 }
131
132 } else {
133 // Need to add console object
134 printf("Stack breaks not available on a %s processor\n", cpu->name().c_str());
135 }
136
137 bs.type = BREAK_CLEAR;
138 break;
139
140 case BREAK_ON_STK_UNDERFLOW:
141 if ((cpu->GetCapabilities() & Processor::eBREAKONSTACKUNDER)
142 == Processor::eBREAKONSTACKUNDER) {
143 // pic_processor should not be referenced here
144 // Should have a GetStack() virtual function in Processor class.
145 // Of course then the Stack class needs to be a virtual class.
146 if (((pic_processor *)(cpu))->stack->set_break_on_underflow(1)) {
147 return breakpoint_number;
148 }
149
150 } else {
151 // Need to add console object
152 printf("Stack breaks not available on a %s processor\n", cpu->name().c_str());
153 }
154
155 bs.type = BREAK_CLEAR;
156 break;
157
158 case BREAK_ON_WDT_TIMEOUT:
159 if ((cpu->GetCapabilities() & Processor::eBREAKONWATCHDOGTIMER)
160 == Processor::eBREAKONWATCHDOGTIMER) {
161 // pic_processor should not be referenced here
162 // Should have a GetStack() virtual function in Processor class.
163 // Of course then the Stack class needs to be a virtual class.
164 ((_14bit_processor *)cpu)->wdt.set_breakpoint(BREAK_ON_WDT_TIMEOUT | breakpoint_number);
165 return breakpoint_number;
166
167 } else {
168 // Need to add console object
169 printf("Watch dog timer breaks not available on a %s processor\n", cpu->name().c_str());
170 }
171
172 default: // Not a valid type
173 bs.type = BREAK_CLEAR;
174 break;
175 }
176
177 return MAX_BREAKPOINTS;
178 }
179
180
181 //------------------------------------------------------------------------
182 //BreakTraceType *m_brt=0;
183
set_breakpoint(TriggerObject * bpo,Processor * pCpu,Expression * pExpr)184 int Breakpoints::set_breakpoint(TriggerObject *bpo, Processor *pCpu, Expression *pExpr)
185 {
186 int bpn = find_free();
187
188 if (bpn >= MAX_BREAKPOINTS || !bpo->set_break()) {
189 delete bpo;
190 return MAX_BREAKPOINTS;
191 }
192
193 BreakStatus &bs = break_status[bpn];
194 bs.bpo = bpo;
195 bs.type = BREAK_MASK; // place holder for now...
196 bs.cpu = pCpu;
197 bpo->bpn = bpn;
198 bpo->set_Expression(pExpr);
199
200 if (get_active_cpu() != nullptr) {
201 get_active_cpu()->NotifyBreakpointSet(bs, bpo);
202 }
203
204 return bpn;
205 }
206
207
208 //------------------------------------------------------------------------
MapComparisonOperatorToBreakOperator(ComparisonOperator * pCompareOp)209 static BreakpointRegister_Value::BRV_Ops MapComparisonOperatorToBreakOperator(ComparisonOperator *pCompareOp)
210 {
211 if (pCompareOp)
212 switch (pCompareOp->isa()) {
213 case ComparisonOperator::eOpEq:
214 return BreakpointRegister_Value::eBREquals;
215
216 case ComparisonOperator::eOpGe:
217 return BreakpointRegister_Value::eBRGreaterThenEquals;
218
219 case ComparisonOperator::eOpGt:
220 return BreakpointRegister_Value::eBRGreaterThen;
221
222 case ComparisonOperator::eOpLe:
223 return BreakpointRegister_Value::eBRLessThenEquals;
224
225 case ComparisonOperator::eOpLt:
226 return BreakpointRegister_Value::eBRLessThen;
227
228 case ComparisonOperator::eOpNe:
229 return BreakpointRegister_Value::eBRNotEquals;
230 }
231
232 return BreakpointRegister_Value::eBRInvalid;
233 }
234
235
236 //------------------------------------------------------------------------
237 //
set_break(gpsimObject::ObjectBreakTypes bt,gpsimObject::ObjectActionTypes at,Register * pReg,Expression * pExpr)238 int Breakpoints::set_break(gpsimObject::ObjectBreakTypes bt, gpsimObject::ObjectActionTypes at,
239 Register *pReg,
240 Expression *pExpr)
241 {
242 int iValue = -1;
243 int iMask = -1;
244 bool bCompiledExpression = false;
245 BreakpointRegister_Value::BRV_Ops op = BreakpointRegister_Value::eBRInvalid;
246 Processor *pCpu = (pReg && pReg->get_cpu()) ? pReg->get_cpu() : get_active_cpu();
247 Register *pRegInExpr = nullptr;
248
249 if (pExpr) {
250 /* attempt to compile expressions of these types:
251 *
252 *
253 * ComparisonOperator
254 * / \
255 * OpAnd LiteralInteger
256 * / \
257 * register_symbol LiteralInteger
258 *
259 * --- OR ---
260 *
261 * ComparisonOperator
262 * / \
263 * register_symbol LiteralInteger
264 *
265 * --- OR ---
266 *
267 * OpAnd (not implemented)
268 * / \
269 * register_symbol LiteralInteger
270 *
271 */
272 ComparisonOperator *pCompareExpr = dynamic_cast<ComparisonOperator *>(pExpr);
273 op = MapComparisonOperatorToBreakOperator(pCompareExpr);
274
275 if (op != BreakpointRegister_Value::eBRInvalid) {
276 OpAnd* pLeftOp = dynamic_cast<OpAnd*>(pCompareExpr->getLeft());
277 LiteralSymbol *pLeftSymbol = pLeftOp ?
278 dynamic_cast<LiteralSymbol*>(pLeftOp->getLeft()) :
279 dynamic_cast<LiteralSymbol*>(pCompareExpr->getLeft());
280 Register *pRegSym = pLeftSymbol ?
281 dynamic_cast<Register *>(pLeftSymbol->GetSymbol()) : nullptr;
282 pRegInExpr = pRegSym ? pRegSym->getReg() : nullptr;
283 //pRegInExpr = pLeftSymbol ? dynamic_cast<Register*>(pLeftSymbol) : 0;
284
285 if (!pRegInExpr) {
286 // Legacy code... try to cast the left most integer into a register.
287 LiteralInteger *pLeftRegAsInteger = pLeftOp ?
288 dynamic_cast<LiteralInteger*>(pLeftOp->getLeft()) :
289 dynamic_cast<LiteralInteger*>(pCompareExpr->getLeft());
290 Integer *pRegAddress = pLeftRegAsInteger ?
291 dynamic_cast<Integer*>(pLeftRegAsInteger->evaluate()) : nullptr;
292 pRegInExpr = (pRegAddress && pCpu) ? &pCpu->rma[(int)pRegAddress->getVal()] : nullptr;
293 delete pRegAddress;
294 }
295
296 LiteralInteger* pRightSymbol = pLeftOp ?
297 dynamic_cast<LiteralInteger*>(pLeftOp->getRight()) : nullptr;
298 Integer *pMask = pRightSymbol ?
299 dynamic_cast<Integer*>(pRightSymbol->evaluate()) : nullptr;
300 iMask = pCpu ? pCpu->register_mask() : iMask;
301 gint64 i64 = 0;
302
303 if (pMask) {
304 pMask->get(i64);
305 iMask = (int)i64;
306 }
307
308 LiteralInteger* pRightValue = dynamic_cast<LiteralInteger*>(pCompareExpr->getRight());
309 Integer *pValue = pRightValue ?
310 dynamic_cast<Integer*>(pRightValue->evaluate()) : nullptr;
311
312 // Now check if this parsing was successful
313 if (pReg == pRegInExpr && pValue) {
314 bCompiledExpression = true;
315 pValue->get(i64);
316 iValue = (int)i64;
317 }
318
319 delete pMask;
320 delete pValue;
321 }
322 }
323
324 // If there was no register passed in as an input and we failed to compile
325 // the expression (and hence unable to extract a register from the expression)
326 // then don't set a break.
327 if (!pReg && !pRegInExpr) {
328 fprintf(stderr, "set_break failed - no register given and expression compile failed\n");
329 return -1;
330 }
331
332 pReg = pReg ? pReg : pRegInExpr;
333
334 if (pReg->address == AN_INVALID_ADDRESS) {
335 fprintf(stderr, "set_break failed - invalid address\n");
336 return -1;
337 }
338
339 if (bt == gpsimObject::eBreakWrite) {
340 if (bCompiledExpression) {
341 delete pExpr;
342 return (at == gpsimObject::eActionLog) ?
343 set_breakpoint(new Log_Register_Write_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu)
344 :
345 set_breakpoint(new Break_register_write_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu);
346
347 } else
348 return (at == gpsimObject::eActionLog) ?
349 set_breakpoint(new Log_Register_Write(pCpu, pReg->address, 0), pCpu, pExpr)
350 :
351 set_breakpoint(new Break_register_write(pCpu, pReg->address, 0), pCpu, pExpr);
352
353 } else if (bt == gpsimObject::eBreakRead) {
354 if (bCompiledExpression) {
355 delete pExpr;
356 return (at == gpsimObject::eActionLog) ?
357 set_breakpoint(new Log_Register_Read_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu)
358 :
359 set_breakpoint(new Break_register_read_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu);
360
361 } else
362 return (at == gpsimObject::eActionLog) ?
363 set_breakpoint(new Log_Register_Read(pCpu, pReg->address, 0), pCpu, pExpr)
364 :
365 set_breakpoint(new Break_register_read(pCpu, pReg->address, 0), pCpu, pExpr);
366
367 } else if (bt == gpsimObject::eBreakChange) {
368 if (bCompiledExpression) {
369 delete pExpr;
370 return (at == gpsimObject::eActionLog) ?
371 set_breakpoint(new Log_Register_Write_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu)
372 :
373 set_breakpoint(new Break_register_write_value(pCpu, pReg->address, 0, iValue, op, iMask), pCpu);
374
375 } else
376 return (at == gpsimObject::eActionLog) ?
377 set_breakpoint(new Log_Register_Write(pCpu, pReg->address, 0), pCpu, pExpr)
378 :
379 set_breakpoint(new Break_register_change(pCpu, pReg->address, 0), pCpu, pExpr);
380 }
381
382 return -1;
383 }
384
385
set_expression(unsigned int bpn,Expression * pExpr)386 bool Breakpoints::set_expression(unsigned int bpn, Expression *pExpr)
387 {
388 if (bpn < MAX_BREAKPOINTS) {
389 BreakStatus &bs = break_status[bpn];
390
391 if (bs.bpo) {
392 bs.bpo->set_Expression(pExpr);
393 return true;
394 }
395 }
396
397 return false;
398 }
399
400
set_execution_break(Processor * cpu,unsigned int address,Expression * pExpr)401 int Breakpoints::set_execution_break(Processor *cpu,
402 unsigned int address,
403 Expression *pExpr)
404 {
405 if (!cpu || !cpu->pma || !cpu->pma->hasValid_opcode_at_address(address)) {
406 return -1;
407 }
408
409 Breakpoint_Instruction *bpi = new Breakpoint_Instruction(cpu, address, 0);
410 return bp.set_breakpoint(bpi, cpu, pExpr);
411 }
412
413
set_notify_break(Processor * cpu,unsigned int address,TriggerObject * f1=nullptr)414 int Breakpoints::set_notify_break(Processor *cpu,
415 unsigned int address,
416 TriggerObject *f1 = nullptr)
417 {
418 GetTraceLog().enable_logging();
419 Notify_Instruction *ni = new Notify_Instruction(cpu, address, 0, f1);
420 return bp.set_breakpoint(ni, cpu);
421 }
422
423
set_profile_start_break(Processor * cpu,unsigned int address,TriggerObject * f1)424 int Breakpoints::set_profile_start_break(Processor *cpu,
425 unsigned int address,
426 TriggerObject *f1)
427 {
428 Profile_Start_Instruction *psi = new Profile_Start_Instruction(cpu, address, 0, f1);
429 return bp.set_breakpoint(psi, cpu);
430 }
431
432
set_profile_stop_break(Processor * cpu,unsigned int address,TriggerObject * f1)433 int Breakpoints::set_profile_stop_break(Processor *cpu,
434 unsigned int address,
435 TriggerObject *f1)
436 {
437 Profile_Stop_Instruction *psi = new Profile_Stop_Instruction(cpu, address, 0, f1);
438 return bp.set_breakpoint(psi, cpu);
439 }
440
441
set_read_break(Processor * cpu,unsigned int register_number)442 int Breakpoints::set_read_break(Processor *cpu, unsigned int register_number)
443 {
444 Break_register_read *brr = new Break_register_read(cpu, register_number, 0);
445 return bp.set_breakpoint(brr, cpu);
446 }
447
448
set_write_break(Processor * cpu,unsigned int register_number)449 int Breakpoints::set_write_break(Processor *cpu, unsigned int register_number)
450 {
451 Break_register_write *brw = new Break_register_write(cpu, register_number, 0);
452 return bp.set_breakpoint(brw, cpu);
453 }
454
455
set_read_value_break(Processor * cpu,unsigned int register_number,unsigned int value,unsigned int mask)456 int Breakpoints::set_read_value_break(Processor *cpu,
457 unsigned int register_number,
458 unsigned int value,
459 unsigned int mask)
460 {
461 return set_read_value_break(cpu, register_number,
462 BreakpointRegister_Value::eBREquals, value, mask);
463 }
464
465
set_read_value_break(Processor * cpu,unsigned int register_number,unsigned int op,unsigned int value,unsigned int mask)466 int Breakpoints::set_read_value_break(Processor *cpu,
467 unsigned int register_number,
468 unsigned int op,
469 unsigned int value,
470 unsigned int mask)
471 {
472 Break_register_read_value *brrv = new Break_register_read_value(cpu,
473 register_number,
474 value,
475 op,
476 BreakpointRegister_Value::eBREquals,
477 mask);
478 return bp.set_breakpoint(brrv, cpu);
479 }
480
481
set_write_value_break(Processor * cpu,unsigned int register_number,unsigned int value,unsigned int mask)482 int Breakpoints::set_write_value_break(Processor *cpu,
483 unsigned int register_number,
484 unsigned int value,
485 unsigned int mask)
486 {
487 return set_write_value_break(cpu, register_number,
488 BreakpointRegister_Value::eBREquals, value, mask);
489 }
490
491
set_write_value_break(Processor * cpu,unsigned int register_number,unsigned int op,unsigned int value,unsigned int mask)492 int Breakpoints::set_write_value_break(Processor *cpu,
493 unsigned int register_number,
494 unsigned int op,
495 unsigned int value,
496 unsigned int mask)
497 {
498 Break_register_write_value *brwv = new Break_register_write_value(cpu,
499 register_number,
500 0,
501 value,
502 op,
503 mask);
504 return bp.set_breakpoint(brwv, cpu);
505 }
506
507
set_change_break(Processor * cpu,unsigned int register_number)508 int Breakpoints::set_change_break(Processor *cpu, unsigned int register_number)
509 {
510 Break_register_change *brc = new Break_register_change(cpu, register_number, 0);
511 return bp.set_breakpoint(brc, cpu);
512 }
513
514
set_cycle_break(Processor * cpu,guint64 future_cycle,TriggerObject * f1)515 int Breakpoints::set_cycle_break(Processor *cpu,
516 guint64 future_cycle,
517 TriggerObject *f1)
518 {
519 return set_breakpoint(Breakpoints::BREAK_ON_CYCLE,
520 cpu,
521 (unsigned int)(future_cycle & 0xffffffff),
522 (unsigned int)(future_cycle >> 32),
523 f1);
524 }
525
526
set_stk_overflow_break(Processor * cpu)527 int Breakpoints::set_stk_overflow_break(Processor *cpu)
528 {
529 return set_breakpoint(Breakpoints::BREAK_ON_STK_OVERFLOW, cpu, 0, 0);
530 }
531
532
set_stk_underflow_break(Processor * cpu)533 int Breakpoints::set_stk_underflow_break(Processor *cpu)
534 {
535 return set_breakpoint(Breakpoints::BREAK_ON_STK_UNDERFLOW, cpu, 0, 0);
536 }
537
538
set_wdt_break(Processor * cpu)539 int Breakpoints::set_wdt_break(Processor *cpu)
540 {
541 if ((cpu->GetCapabilities() & Processor::eBREAKONWATCHDOGTIMER)
542 == Processor::eBREAKONWATCHDOGTIMER) {
543 // Set a wdt break only if one is not already set.
544 if (!cpu14->wdt.hasBreak()) {
545 return set_breakpoint(Breakpoints::BREAK_ON_WDT_TIMEOUT, cpu, 0, 0);
546 }
547
548 } else {
549 // Need to add console object
550 printf("Watch dog timer breaks not available on a %s processor\n", cpu->name().c_str());
551 }
552
553 return MAX_BREAKPOINTS;
554 }
555
556
set_notify_read(Processor * cpu,unsigned int register_number)557 int Breakpoints::set_notify_read(Processor *cpu,
558 unsigned int register_number)
559 {
560 GetTraceLog().enable_logging();
561 Log_Register_Read *lrr = new Log_Register_Read(cpu, register_number, 0);
562 return bp.set_breakpoint(lrr, cpu);
563 }
564
565
set_notify_write(Processor * cpu,unsigned int register_number)566 int Breakpoints::set_notify_write(Processor *cpu,
567 unsigned int register_number)
568 {
569 GetTraceLog().enable_logging();
570 Log_Register_Write *lrw = new Log_Register_Write(cpu, register_number, 0);
571 return bp.set_breakpoint(lrw, cpu);
572 }
573
574
set_notify_read_value(Processor * cpu,unsigned int register_number,unsigned int value,unsigned int mask)575 int Breakpoints::set_notify_read_value(Processor *cpu,
576 unsigned int register_number,
577 unsigned int value,
578 unsigned int mask)
579 {
580 GetTraceLog().enable_logging();
581 Log_Register_Read_value *lrrv = new Log_Register_Read_value(cpu,
582 register_number,
583 0,
584 value,
585 BreakpointRegister_Value::eBREquals,
586 mask);
587 return bp.set_breakpoint(lrrv, cpu);
588 }
589
590
set_notify_write_value(Processor * cpu,unsigned int register_number,unsigned int value,unsigned int mask)591 int Breakpoints::set_notify_write_value(Processor *cpu,
592 unsigned int register_number,
593 unsigned int value,
594 unsigned int mask)
595 {
596 GetTraceLog().enable_logging();
597 Log_Register_Write_value *lrwv = new Log_Register_Write_value(cpu,
598 register_number,
599 0,
600 value,
601 BreakpointRegister_Value::eBREquals,
602 mask);
603 return bp.set_breakpoint(lrwv, cpu);
604 }
605
606
check_cycle_break(unsigned int bpn)607 int Breakpoints::check_cycle_break(unsigned int bpn)
608 {
609 std::cout << "cycle break: 0x" << std::hex << get_cycles().get()
610 << std::dec << " = " << get_cycles().get() << '\n';
611 halt();
612
613 if (bpn < MAX_BREAKPOINTS) {
614 if (break_status[bpn].bpo) {
615 break_status[bpn].bpo->callback();
616 }
617
618 //trace.breakpoint( (Breakpoints::BREAK_ON_CYCLE>>8) );
619 //trace.raw(m_brt->type() | bpn);
620 clear(bpn);
621 }
622
623 return 1;
624 }
625
626
dump(TriggerObject * pTO)627 bool Breakpoints::dump(TriggerObject *pTO)
628 {
629 if (!pTO) {
630 return false;
631 }
632
633 pTO->print();
634 return true;
635 }
636
637
dump1(unsigned int bp_num,int dump_type)638 bool Breakpoints::dump1(unsigned int bp_num, int dump_type)
639 {
640 if (!bIsValid(bp_num)) {
641 printf("Break point number: %u is out of range\n", bp_num);
642 return false;
643 }
644
645 BreakStatus &bs = break_status[bp_num];
646
647 if (bs.bpo) {
648 switch (dump_type) {
649 case BREAK_ON_EXECUTION:
650 if (dynamic_cast<RegisterAssertion *>(bs.bpo) != nullptr) {
651 // for 'break e' we skip RegisterAssertions
652 // and dump user execution breaks.
653 return false;
654 }
655
656 break;
657
658 case BREAK_ON_REG_WRITE:
659 if (dynamic_cast<Break_register_write *>(bs.bpo) != nullptr ||
660 dynamic_cast<Break_register_write_value*>(bs.bpo) != nullptr) {
661 // for 'break w' we dump register write classes
662 break;
663 }
664
665 return false;
666
667 case BREAK_ON_REG_READ:
668 if (dynamic_cast<Break_register_read *>(bs.bpo) != nullptr ||
669 dynamic_cast<Break_register_read_value*>(bs.bpo) != nullptr) {
670 // for 'break r' we dump register read classes
671 break;
672 }
673
674 default:
675 break;
676 }
677
678 return dump(bs.bpo);
679
680 } else {
681 BREAKPOINT_TYPES break_type = break_status[bp_num].type;
682
683 switch (break_type) {
684 case BREAK_ON_CYCLE: {
685 const char * pFormat = "%d: cycle 0x%" PRINTF_INT64_MODIFIER "x = %" PRINTF_INT64_MODIFIER "d\n";
686 guint64 cyc = bs.arg2;
687 cyc = (cyc << 32) | bs.arg1;
688 GetUserInterface().DisplayMessage(pFormat, bp_num, cyc, cyc);
689 }
690 break;
691
692 case BREAK_ON_STK_UNDERFLOW:
693 case BREAK_ON_STK_OVERFLOW:
694 std::cout << std::hex << std::setw(0) << bp_num << ": " << bs.cpu->name() << " ";
695 std::cout << "stack " << ((break_type == BREAK_ON_STK_OVERFLOW) ? "ov" : "und") << "er flow\n";
696 break;
697
698 case BREAK_ON_WDT_TIMEOUT:
699 std::cout << std::hex << std::setw(0) << bp_num << ": " << bs.cpu->name() << " ";
700 std::cout << "wdt time out\n";
701 break;
702
703 default:
704 return false;
705 break;
706 }
707 }
708
709 return true;
710 }
711
712
dump(int dump_type)713 void Breakpoints::dump(int dump_type)
714 {
715 bool have_breakpoints = false;
716
717 if (dump_type != BREAK_ON_CYCLE) {
718 for (int i = 0; i < m_iMaxAllocated; i++) {
719 if (dump1(i, dump_type)) {
720 have_breakpoints = true;
721 }
722 }
723 }
724
725 if (dump_type == BREAK_DUMP_ALL || dump_type == BREAK_ON_CYCLE) {
726 std::cout << "Internal Cycle counter break points\n";
727 get_cycles().dump_breakpoints();
728 have_breakpoints = true;
729 std::cout << '\n';
730 }
731
732 if (!have_breakpoints) {
733 std::cout << "No user breakpoints are set\n";
734 }
735 }
736
737
find_previous(Processor * cpu,unsigned int address,instruction * _this)738 instruction *Breakpoints::find_previous(Processor *cpu,
739 unsigned int address,
740 instruction *_this)
741 {
742 Breakpoint_Instruction *p;
743 p = (Breakpoint_Instruction*) cpu->pma->getFromAddress(address);
744
745 if (!_this || p == _this) {
746 return nullptr;
747 }
748
749 while (p->getReplaced() != _this) {
750 p = (Breakpoint_Instruction*)p->getReplaced();
751 }
752
753 return p;
754 }
755
756
clear(unsigned int b)757 void Breakpoints::clear(unsigned int b)
758 {
759 if (!bIsValid(b)) {
760 return;
761 }
762
763 BreakStatus &bs = break_status[b];
764
765 //cout << "clearing bp:"<<dec<<b<<endl;
766 if (bs.bpo) {
767 bs.bpo->clear();
768 bs.type = BREAK_CLEAR;
769 get_active_cpu()->NotifyBreakpointCleared(bs, bs.bpo);
770 delete bs.bpo;
771 bs.bpo = nullptr;
772 return;
773 }
774
775 switch (bs.type) {
776 case BREAK_ON_CYCLE:
777 bs.type = BREAK_CLEAR;
778 //cout << "Cleared cycle breakpoint number " << b << '\n';
779 break;
780
781 case BREAK_ON_STK_OVERFLOW:
782 bs.type = BREAK_CLEAR;
783
784 if ((bs.cpu->GetCapabilities() & Processor::eSTACK) == Processor::eSTACK) {
785 if (((pic_processor *)(bs.cpu))->stack->set_break_on_overflow(0)) {
786 std::cout << "Cleared stack overflow break point.\n";
787
788 } else {
789 std::cout << "Stack overflow break point is already cleared.\n";
790 }
791 }
792
793 break;
794
795 case BREAK_ON_STK_UNDERFLOW:
796 bs.type = BREAK_CLEAR;
797
798 if ((bs.cpu->GetCapabilities() & Processor::eSTACK)
799 == Processor::eSTACK) {
800 if (((pic_processor *)(bs.cpu))->stack->set_break_on_underflow(0)) {
801 std::cout << "Cleared stack underflow break point.\n";
802
803 } else {
804 std::cout << "Stack underflow break point is already cleared.\n";
805 }
806 }
807
808 break;
809
810 case BREAK_ON_WDT_TIMEOUT:
811 bs.type = BREAK_CLEAR;
812
813 if ((bs.cpu->GetCapabilities() & Processor::eBREAKONWATCHDOGTIMER)
814 == Processor::eBREAKONWATCHDOGTIMER) {
815 std::cout << "Cleared wdt timeout breakpoint number " << b << '\n';
816 ((_14bit_processor *)bs.cpu)->wdt.set_breakpoint(0);
817 }
818
819 break;
820
821 default:
822 bs.type = BREAK_CLEAR;
823 break;
824 }
825
826 get_active_cpu()->NotifyBreakpointCleared(bs, nullptr);
827 }
828
829
bIsValid(unsigned int b)830 bool Breakpoints::bIsValid(unsigned int b)
831 {
832 return b < MAX_BREAKPOINTS;
833 }
834
835
bIsClear(unsigned int b)836 bool Breakpoints::bIsClear(unsigned int b)
837 {
838 return bIsValid(b) && break_status[b].type == BREAK_CLEAR;
839 }
840
841
set_message(unsigned int b,std::string & m)842 void Breakpoints::set_message(unsigned int b, std::string &m)
843 {
844 if (bIsValid(b) && break_status[b].type != BREAK_CLEAR && break_status[b].bpo) {
845 break_status[b].bpo->new_message(m);
846 }
847 }
848
849
850 //
851 // dump_traced
852 // Called by the trace class to display a breakpoint that is in the
853 // trace buffer.
854
dump_traced(unsigned int b)855 void Breakpoints::dump_traced(unsigned int b)
856 {
857 BREAKPOINT_TYPES break_type = (BREAKPOINT_TYPES)((b & 0xff0000) << 8);
858
859 switch (break_type) {
860 case BREAK_ON_EXECUTION:
861 std::cout << "execution at " << std::hex << std::setw(4) << std::setfill('0') << (b & 0xffff) << '\n';
862 break;
863
864 case BREAK_ON_REG_WRITE:
865 std::cout << "reg write: " << std::hex << std::setw(2) << std::setfill('0') << (b & 0xff) << '\n';
866 break;
867
868 case BREAK_ON_REG_WRITE_VALUE:
869 std::cout << "wrote " << std::hex << std::setw(2) << std::setfill('0') << ((b & 0xff00) >> 8) <<
870 " to register " << std::hex << std::setw(2) << std::setfill('0') << (b & 0xff) << '\n';
871 break;
872
873 case BREAK_ON_REG_READ:
874 std::cout << "reg write: " << std::hex << std::setw(2) << std::setfill('0') << (b & 0xff) << '\n';
875 break;
876
877 case BREAK_ON_REG_READ_VALUE:
878 std::cout << "read " << std::hex << std::setw(2) << std::setfill('0') << ((b & 0xff00) >> 8) <<
879 " from register " << std::hex << std::setw(2) << std::setfill('0') << (b & 0xff) << '\n';
880 break;
881
882 case BREAK_ON_CYCLE:
883 std::cout << "cycle \n";
884 break;
885
886 case BREAK_ON_WDT_TIMEOUT:
887 std::cout << "wdt time out\n";
888 break;
889
890 default:
891 std::cout << "unknown\n";
892 }
893 }
894
895
896 // Clear all break points that are set for a specific processor
897 // This only be called when a processor is being removed and not when a user
898 // wants to clear the break points. Otherwise, internal break points like
899 // invalid register accesses will get cleared.
900
clear_all(Processor * c)901 void Breakpoints::clear_all(Processor *c)
902 {
903 GetTraceLog().close_logfile();
904
905 for (int i = 0; i < MAX_BREAKPOINTS; i++)
906 if (break_status[i].type != BREAK_CLEAR && break_status[i].cpu == c) {
907 clear(i);
908 }
909 }
910
911
clear_all_set_by_user(Processor * c)912 void Breakpoints::clear_all_set_by_user(Processor *c)
913 {
914 for (int i = 0; i < MAX_BREAKPOINTS; i++) {
915 if ((c == break_status[i].cpu) && (break_status[i].type != BREAK_ON_INVALID_FR)) {
916 clear(i);
917 }
918 }
919 }
920
921
922 //--------------------------------------------------
923 // Clear all of the break points that are set on a register
924 //
925 // FIXME -- this tacitly assumes "register memory". Thus it's
926 // not possible to use this function on EEPROM or module registers.
927
clear_all_register(Processor * c,gint64 address)928 void Breakpoints::clear_all_register(Processor *c, gint64 address)
929 {
930 if (!c || address < 0 || address > c->register_memory_size()) {
931 return;
932 }
933
934 while (c->registers[address]->isa() == Register::BP_REGISTER) {
935 BreakpointRegister *nr = dynamic_cast<BreakpointRegister *>(c->registers[address]);
936
937 if (!nr) {
938 return;
939 }
940
941 bp.clear(nr->bpn & ~Breakpoints::BREAK_MASK);
942 }
943 }
944
945
halt()946 void Breakpoints::halt()
947 {
948 if (get_use_icd()) {
949 icd_halt();
950 return;
951 }
952
953 global_break |= GLOBAL_STOP_RUNNING;
954
955 if (m_bExitOnBreak) {
956 // Let the UI or client code choose how and
957 // when to exit.
958 GetUserInterface().NotifyExitOnBreak(0);
959 }
960 }
961
962
Breakpoints()963 Breakpoints::Breakpoints()
964 {
965 for (int i = 0; i < MAX_BREAKPOINTS; i++) {
966 break_status[i].type = BREAK_CLEAR;
967 }
968 }
969
970
971 //----------------------------------------------------------------------------
eval_Expression()972 bool Breakpoint_Instruction::eval_Expression()
973 {
974 if (bHasExpression()) {
975 return !TriggerObject::eval_Expression();
976 }
977
978 return true;
979 }
980
981
execute()982 void Breakpoint_Instruction::execute()
983 {
984 if ((cpu->simulation_mode == eSM_RUNNING) &&
985 (simulation_start_cycle != get_cycles().get()) &&
986 eval_Expression()) {
987 invokeAction();
988
989 } else {
990 m_replaced->execute();
991 }
992 }
993
994
Breakpoint_Instruction(Processor * new_cpu,unsigned int new_address,unsigned int bp)995 Breakpoint_Instruction::Breakpoint_Instruction(Processor *new_cpu,
996 unsigned int new_address,
997 unsigned int bp)
998 : TriggerObject(0), address(new_address)
999 {
1000 cpu = new_cpu;
1001 opcode = 0xffffffff;
1002 bpn = bp;
1003 m_replaced = new_cpu->pma->getFromAddress(address);
1004 set_action(new SimpleTriggerAction(this));
1005 }
1006
1007
~Breakpoint_Instruction()1008 Breakpoint_Instruction::~Breakpoint_Instruction()
1009 {
1010 }
1011
1012
get_cpu()1013 Processor* Breakpoint_Instruction::get_cpu()
1014 {
1015 return dynamic_cast<Processor *>(cpu);
1016 }
1017
1018
1019 //-------------------------------------------------------------------
1020
set_break()1021 bool Breakpoint_Instruction::set_break()
1022 {
1023 if (get_use_icd()) {
1024 bp.clear_all(get_cpu());
1025 }
1026
1027 unsigned int uIndex = get_cpu()->map_pm_address2index(address);
1028
1029 if (uIndex < get_cpu()->program_memory_size()) {
1030 m_replaced = get_cpu()->pma->getFromIndex(uIndex);
1031 get_cpu()->pma->putToIndex(uIndex, this);
1032
1033 if (get_use_icd()) {
1034 icd_set_break(address);
1035 }
1036
1037 return true;
1038 }
1039
1040 return false;
1041 }
1042
1043
print()1044 void Breakpoint_Instruction::print()
1045 {
1046 // Output example
1047 // 42: p17c756 Execution at 0x0123
1048 instruction *pReplaced = getReplaced();
1049 gpsimObject *pLineSym = pReplaced ? pReplaced->getLineSymbol() : nullptr;
1050 const char *pLabel = pLineSym ? pLineSym->name().c_str() : "no label";
1051 const char * pFormat = *pLabel == 0 ? "%d: %s %s at %s0x%x\n"
1052 : "%d: %s %s at %s(0x%x)\n";
1053 GetUserInterface().DisplayMessage(pFormat,
1054 bpn, cpu->name().c_str(), bpName(), pLabel, address);
1055 TriggerObject::print();
1056 }
1057
1058
printTraced(Trace * pTrace,unsigned int,char * pBuf,int szBuf)1059 int Breakpoint_Instruction::printTraced(Trace *pTrace, unsigned int /* tbi */ ,
1060 char *pBuf, int szBuf)
1061
1062 {
1063 if (!pBuf || !pTrace) {
1064 return 0;
1065 }
1066
1067 int m;
1068
1069 if (bHasExpression()) {
1070 char buf[256];
1071 printExpression(buf, sizeof(buf));
1072 m = snprintf(pBuf, szBuf,
1073 " assertion at 0x%04x, expr:%s", address, buf);
1074
1075 } else
1076 m = snprintf(pBuf, szBuf,
1077 " execution at 0x%04x", address);
1078
1079 return m > 0 ? m : 0;
1080 }
1081
1082
clear()1083 void Breakpoint_Instruction::clear()
1084 {
1085 if (get_use_icd()) {
1086 icd_clear_break();
1087 }
1088
1089 get_cpu()->pma->clear_break_at_address(address, this);
1090 instruction *pInst = get_cpu()->pma->getFromAddress(address);
1091 /*
1092 cout << "about to update cleared instruction breakpoint:" << pInst
1093 << " this:" << this
1094 << " address: 0x" << hex << address
1095 << endl;
1096 */
1097 pInst->update();
1098 }
1099
1100
1101 //------------------------------------------------------------------------
execute()1102 void Notify_Instruction::execute()
1103 {
1104 if (callback) {
1105 callback->callback();
1106 }
1107
1108 m_replaced->execute();
1109 }
1110
1111
Notify_Instruction(Processor * cpu,unsigned int address,unsigned int bp,TriggerObject * cb)1112 Notify_Instruction::Notify_Instruction(Processor *cpu,
1113 unsigned int address,
1114 unsigned int bp,
1115 TriggerObject *cb) :
1116 Breakpoint_Instruction(cpu, address, bp)
1117 {
1118 callback = cb;
1119 }
1120
1121
~Notify_Instruction()1122 Notify_Instruction::~Notify_Instruction()
1123 {
1124 }
1125
1126
1127 //------------------------------------------------------------------------
Profile_Start_Instruction(Processor * cpu,unsigned int address,unsigned int bp,TriggerObject * cb)1128 Profile_Start_Instruction::Profile_Start_Instruction(Processor *cpu,
1129 unsigned int address,
1130 unsigned int bp,
1131 TriggerObject *cb) :
1132 Notify_Instruction(cpu, address, bp, cb)
1133 {
1134 }
1135
1136
Profile_Stop_Instruction(Processor * cpu,unsigned int address,unsigned int bp,TriggerObject * cb)1137 Profile_Stop_Instruction::Profile_Stop_Instruction(Processor *cpu,
1138 unsigned int address,
1139 unsigned int bp,
1140 TriggerObject *cb) :
1141 Notify_Instruction(cpu, address, bp, cb)
1142 {
1143 }
1144
1145
1146 //------------------------------------------------------------------------------
RegisterAssertion(Processor * cpu,unsigned int address,unsigned int bp,unsigned int _regAddress,unsigned int _regMask,unsigned int _regValue,bool _bPostAssertion)1147 RegisterAssertion::RegisterAssertion(Processor *cpu,
1148 unsigned int address,
1149 unsigned int bp,
1150 unsigned int _regAddress,
1151 unsigned int _regMask,
1152 unsigned int _regValue,
1153 bool _bPostAssertion) :
1154 Breakpoint_Instruction(cpu, address, bp),
1155 regAddress(_regAddress),
1156 regMask(_regMask),
1157 regValue(_regValue),
1158 bPostAssertion(_bPostAssertion),
1159 m_pfnIsAssertionBreak(IsAssertionEqualsBreakCondition)
1160 {
1161 }
1162
1163
RegisterAssertion(Processor * cpu,unsigned int address,unsigned int bp,unsigned int _regAddress,unsigned int _regMask,unsigned int _operator,unsigned int _regValue,bool _bPostAssertion)1164 RegisterAssertion::RegisterAssertion(Processor *cpu,
1165 unsigned int address,
1166 unsigned int bp,
1167 unsigned int _regAddress,
1168 unsigned int _regMask,
1169 unsigned int _operator,
1170 unsigned int _regValue,
1171 bool _bPostAssertion) :
1172 Breakpoint_Instruction(cpu, address, bp),
1173 regAddress(_regAddress),
1174 regMask(_regMask),
1175 regValue(_regValue),
1176 bPostAssertion(_bPostAssertion)
1177 {
1178 switch (_operator) {
1179 case eRAEquals:
1180 m_pfnIsAssertionBreak = IsAssertionEqualsBreakCondition;
1181 break;
1182
1183 case eRANotEquals:
1184 m_pfnIsAssertionBreak = IsAssertionNotEqualsBreakCondition;
1185 break;
1186
1187 case eRAGreaterThen:
1188 m_pfnIsAssertionBreak = IsAssertionGreaterThenBreakCondition;
1189 break;
1190
1191 case eRALessThen:
1192 m_pfnIsAssertionBreak = IsAssertionLessThenBreakCondition;
1193 break;
1194
1195 case eRAGreaterThenEquals:
1196 m_pfnIsAssertionBreak = IsAssertionGreaterThenEqualsBreakCondition;
1197 break;
1198
1199 case eRALessThenEquals:
1200 m_pfnIsAssertionBreak = IsAssertionLessThenEqualsBreakCondition;
1201 break;
1202
1203 default:
1204 assert(false);
1205 break;
1206 }
1207 }
1208
1209
~RegisterAssertion()1210 RegisterAssertion::~RegisterAssertion()
1211 {
1212 }
1213
1214
IsAssertionEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1215 bool RegisterAssertion::IsAssertionEqualsBreakCondition(unsigned int uRegValue,
1216 unsigned int uRegMask, unsigned int uRegTestValue)
1217 {
1218 return (uRegValue & uRegMask) != uRegTestValue;
1219 }
1220
1221
IsAssertionNotEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1222 bool RegisterAssertion::IsAssertionNotEqualsBreakCondition(unsigned int uRegValue,
1223 unsigned int uRegMask, unsigned int uRegTestValue)
1224 {
1225 return (uRegValue & uRegMask) == uRegTestValue;
1226 }
1227
1228
IsAssertionGreaterThenBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1229 bool RegisterAssertion::IsAssertionGreaterThenBreakCondition(unsigned int uRegValue,
1230 unsigned int uRegMask, unsigned int uRegTestValue)
1231 {
1232 return (uRegValue & uRegMask) <= uRegTestValue;
1233 }
1234
1235
IsAssertionLessThenBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1236 bool RegisterAssertion::IsAssertionLessThenBreakCondition(unsigned int uRegValue,
1237 unsigned int uRegMask, unsigned int uRegTestValue)
1238 {
1239 return (uRegValue & uRegMask) >= uRegTestValue;
1240 }
1241
1242
IsAssertionGreaterThenEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1243 bool RegisterAssertion::IsAssertionGreaterThenEqualsBreakCondition(unsigned int uRegValue,
1244 unsigned int uRegMask, unsigned int uRegTestValue)
1245 {
1246 return (uRegValue & uRegMask) < uRegTestValue;
1247 }
1248
1249
IsAssertionLessThenEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1250 bool RegisterAssertion::IsAssertionLessThenEqualsBreakCondition(unsigned int uRegValue,
1251 unsigned int uRegMask, unsigned int uRegTestValue)
1252 {
1253 return (uRegValue & uRegMask) > uRegTestValue;
1254 }
1255
1256
1257 //------------------------------------------------------------------------------
execute()1258 void RegisterAssertion::execute()
1259 {
1260 // For "post" assertions, the instruction is simulated first
1261 // and then the register assertion is checked.
1262 if (bPostAssertion && m_replaced) {
1263 m_replaced->execute();
1264 }
1265
1266 // If the assertion is true, and the "phase" of the instruction is
1267 // '0' then halt the simulation. Note, the reason for checking "phase"
1268 // is to ensure the assertion applies to the the proper cycle of a
1269 // multi-cycle instruction. For example, an assertion applied to a
1270 // a "GOTO" instruction should only get checked before the instruction
1271 // executes if it's a pre-assertion or after it completes if it's a
1272 // post assertion.
1273 unsigned int curRegValue = PCPU->rma[regAddress].get_value();
1274
1275 if (m_pfnIsAssertionBreak(curRegValue, regMask, regValue) &&
1276 (PCPU->pc->get_phase() == 0)) {
1277 std::cout << "Caught Register "
1278 << (bPostAssertion ? "post " : "")
1279 << "assertion "
1280 << "while excuting at address 0x" << std::hex << address << '\n';
1281 std::cout << "register 0x"
1282 << std::hex
1283 << regAddress
1284 << " = 0x"
1285 << curRegValue << '\n';
1286 std::cout << "0x" << PCPU->rma[regAddress].get_value()
1287 << " & 0x" << regMask
1288 << " != 0x" << regValue << '\n';
1289 std::cout << " regAddress =0x" << regAddress
1290 << " regMask = 0x" << regMask
1291 << " regValue = 0x" << regValue << '\n';
1292 PCPU->Debug();
1293
1294 if ((PCPU->simulation_mode == eSM_RUNNING) &&
1295 (simulation_start_cycle != get_cycles().get())) {
1296 eval_Expression();
1297 invokeAction();
1298 trace.raw(m_brt->type(1) | curRegValue);
1299 return;
1300 }
1301 }
1302
1303 // If this is not a post assertion, then the instruction executes after
1304 // the instruction simulates.
1305
1306 if (!bPostAssertion && m_replaced) {
1307 m_replaced->execute();
1308 }
1309 }
1310
1311
1312 //------------------------------------------------------------------------------
print()1313 void RegisterAssertion::print()
1314 {
1315 Breakpoint_Instruction::print();
1316 Register & pReg = PCPU->rma[regAddress];
1317 std::string & sName = pReg.name();
1318 const char * pFormat = sName.empty()
1319 ? " break when register %s0x%x ANDed with 0x%x equals 0x%x\n"
1320 : " break when register %s(0x%x) ANDed with 0x%x equals 0x%x\n" ;
1321 GetUserInterface().DisplayMessage(pFormat,
1322 sName.c_str(), regAddress, regMask, regValue);
1323 TriggerObject::print();
1324 }
1325
1326
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)1327 int RegisterAssertion::printTraced(Trace *pTrace, unsigned int tbi,
1328 char *pBuf, int szBuf)
1329 {
1330 if (!pBuf || pTrace) {
1331 return 0;
1332 }
1333
1334 unsigned int valueWritten = pTrace->get(tbi + 1) & 0xffff;
1335 int m = snprintf(pBuf, szBuf,
1336 " Register Assertion PC=0x%04x, reg[0x%x]==0x%x != 0x%x",
1337 address, regAddress, valueWritten, regValue);
1338 return m > 0 ? m : 0;
1339 }
1340
1341
1342 //------------------------------------------------------------------------------
1343 #if 0
1344 class BreakpointRegisterAction : public TriggerAction {
1345 public:
1346 BreakpointRegisterAction(BreakpointRegister *pbpr);
1347 virtual ~BreakpointRegisterAction();
1348 virtual void action();
1349 private:
1350 BreakpointRegister *m_pbpr;
1351 };
1352
1353 BreakpointRegisterAction::BreakpointRegisterAction(BreakpointRegister *pbpr)
1354 : m_pbpr(pbpr)
1355 {
1356 }
1357 BreakpointRegisterAction:: ~BreakpointRegisterAction()
1358 {
1359 }
1360 void BreakpointRegisterAction::action()
1361 {
1362 if (m_pbpr) {
1363 m_pbpr->takeAction();
1364 }
1365 }
1366 #endif
1367 //------------------------------------------------------------------------------
1368 /*
1369 BreakpointRegister::BreakpointRegister()
1370 : TriggerObject(new BreakpointRegisterAction(this))
1371 {
1372 }
1373 */
1374
1375
~BreakpointRegister()1376 BreakpointRegister::~BreakpointRegister()
1377 {
1378 }
1379
1380
BreakpointRegister(Processor * _cpu,TriggerAction * pTA,Register * pRepl)1381 BreakpointRegister::BreakpointRegister(Processor *_cpu,
1382 TriggerAction *pTA,
1383 Register *pRepl)
1384 : Register(_cpu, "", 0), TriggerObject(pTA)
1385 {
1386 setReplaced(pRepl);
1387 }
1388
1389
BreakpointRegister(Processor * _cpu,TriggerAction * ta,int _repl,int bp)1390 BreakpointRegister::BreakpointRegister(Processor *_cpu, TriggerAction *ta,
1391 int _repl, int bp)
1392 : Register(_cpu, "", 0), TriggerObject(ta)
1393 {
1394 bpn = bp;
1395 replace(_cpu, _repl);
1396 address = _repl;
1397 }
1398
1399
invokeAction()1400 void BreakpointRegister::invokeAction()
1401 {
1402 if (eval_Expression()) {
1403 TriggerObject::invokeAction();
1404 }
1405 }
1406
1407
takeAction()1408 void BreakpointRegister::takeAction()
1409 {
1410 }
1411
1412
replace(Processor * _cpu,unsigned int reg)1413 void BreakpointRegister::replace(Processor *_cpu, unsigned int reg)
1414 {
1415 if (_cpu) {
1416 cpu = _cpu;
1417 _cpu->rma.insertRegister(reg, this);
1418 }
1419
1420 update();
1421 }
1422
1423
clear(unsigned int)1424 unsigned int BreakpointRegister::clear(unsigned int /* bp_num */ )
1425 {
1426 clear();
1427 return 1;
1428 }
1429
1430
1431 /// BreakpointRegister::clear() will delete itself from the
1432 /// chain of BreakpointRegister objects.
1433 /// All derived classes that override this function need to
1434 /// call this function of this base class.
1435
1436 // Note: There should be a RegisterChain class and this code
1437 // should exist in the RegisterChain class. get_cpu()->registers
1438 // would then be an array of RegisterChains.
clear()1439 void BreakpointRegister::clear()
1440 {
1441 // FIXME, we don't know if this breakpoint register is actually associated
1442 // with the active cpu or not. It looks like we need a way for either the
1443 // registers to know in which array they're stored OR the Module class needs
1444 // to provide a 'removeRegister()' method.
1445 if (get_cpu()) {
1446 get_cpu()->rma.removeRegister(address, this);
1447 get_cpu()->registers[address]->update();
1448 }
1449 }
1450
1451
set_break()1452 bool BreakpointRegister::set_break()
1453 {
1454 return true;
1455 }
1456
1457
print()1458 void BreakpointRegister::print()
1459 {
1460 // FIXME - broke with new symbol table.
1461 Register * pReg = nullptr; // get_symbol_table().findRegister(address);
1462
1463 if (pReg)
1464 GetUserInterface().DisplayMessage("%d: %s %s: %s(0x%x)\n",
1465 bpn, cpu->name().c_str(),
1466 bpName(), pReg->name().c_str(),
1467 address);
1468
1469 else
1470 GetUserInterface().DisplayMessage("%d: %s: reg(0x%x)\n",
1471 bpn, bpName(),
1472 address);
1473
1474 TriggerObject::print();
1475 }
1476
1477
printTraced(Trace * pTrace,unsigned int,char * pBuf,int szBuf)1478 int BreakpointRegister::printTraced(Trace *pTrace, unsigned int /* tbi */ ,
1479 char *pBuf, int szBuf)
1480 {
1481 if (!pBuf || pTrace) {
1482 return 0;
1483 }
1484
1485 int m = snprintf(pBuf, szBuf,
1486 " Breakpoint register ");
1487 return m > 0 ? m : 0;
1488 }
1489
1490
name() const1491 std::string &BreakpointRegister::name() const
1492 {
1493 return m_replaced ? m_replaced->name() : gpsimObject::name();
1494 }
1495
1496
put_value(unsigned int new_value)1497 void BreakpointRegister::put_value(unsigned int new_value)
1498 {
1499 getReplaced()->put_value(new_value);
1500 }
1501
1502
put(unsigned int new_value)1503 void BreakpointRegister::put(unsigned int new_value)
1504 {
1505 getReplaced()->put(new_value);
1506 }
1507
1508
putRV(RegisterValue rv)1509 void BreakpointRegister::putRV(RegisterValue rv)
1510 {
1511 getReplaced()->putRV(rv);
1512 }
1513
1514
get_value()1515 unsigned int BreakpointRegister::get_value()
1516 {
1517 return (getReplaced()->get_value());
1518 }
1519
1520
getRV()1521 RegisterValue BreakpointRegister::getRV()
1522 {
1523 return getReplaced()->getRV();
1524 }
1525
1526
getRVN()1527 RegisterValue BreakpointRegister::getRVN()
1528 {
1529 return getReplaced()->getRVN();
1530 }
1531
1532
get()1533 unsigned int BreakpointRegister::get()
1534 {
1535 return (getReplaced()->get());
1536 }
1537
1538
getReg()1539 Register *BreakpointRegister::getReg()
1540 {
1541 return getReplaced() ? getReplaced()->getReg() : this;
1542 }
1543
1544
setbit(unsigned int bit_number,bool new_value)1545 void BreakpointRegister::setbit(unsigned int bit_number, bool new_value)
1546 {
1547 getReplaced()->setbit(bit_number, new_value);
1548 }
1549
1550
get_bit(unsigned int bit_number)1551 bool BreakpointRegister::get_bit(unsigned int bit_number)
1552 {
1553 return (getReplaced()->get_bit(bit_number));
1554 }
1555
1556
get_bit_voltage(unsigned int bit_number)1557 double BreakpointRegister::get_bit_voltage(unsigned int bit_number)
1558 {
1559 return (getReplaced()->get_bit_voltage(bit_number));
1560 }
1561
1562
hasBreak()1563 bool BreakpointRegister::hasBreak()
1564 {
1565 return true;
1566 }
1567
1568
update()1569 void BreakpointRegister::update()
1570 {
1571 if (getReplaced()) {
1572 getReplaced()->update();
1573 }
1574 }
1575
1576
add_xref(void * an_xref)1577 void BreakpointRegister::add_xref(void *an_xref)
1578 {
1579 if (getReplaced()) {
1580 getReplaced()->add_xref(an_xref);
1581 }
1582 }
1583
1584
remove_xref(void * an_xref)1585 void BreakpointRegister::remove_xref(void *an_xref)
1586 {
1587 if (getReplaced()) {
1588 getReplaced()->remove_xref(an_xref);
1589 }
1590 }
1591
1592
1593 //------------------------------------------------------------------------
1594
1595 BreakpointRegister_Value::
BreakpointRegister_Value(Processor * _cpu,int _repl,int bp,unsigned int bv,unsigned int _operator,unsigned int bm)1596 BreakpointRegister_Value(Processor *_cpu,
1597 int _repl,
1598 int bp,
1599 unsigned int bv,
1600 unsigned int _operator,
1601 unsigned int bm)
1602 : BreakpointRegister(_cpu, 0, _repl, bp)
1603 {
1604 m_uDefRegMask = _cpu->register_mask();
1605 break_value = bv;
1606 break_mask = bm;
1607
1608 switch (_operator) {
1609 case eBREquals:
1610 m_pfnIsBreak = IsEqualsBreakCondition;
1611 m_sOperator = "==";
1612 break;
1613
1614 case eBRNotEquals:
1615 m_pfnIsBreak = IsNotEqualsBreakCondition;
1616 m_sOperator = "!=";
1617 break;
1618
1619 case eBRGreaterThen:
1620 m_pfnIsBreak = IsGreaterThenBreakCondition;
1621 m_sOperator = ">";
1622 break;
1623
1624 case eBRLessThen:
1625 m_pfnIsBreak = IsLessThenBreakCondition;
1626 m_sOperator = "<";
1627 break;
1628
1629 case eBRGreaterThenEquals:
1630 m_pfnIsBreak = IsGreaterThenEqualsBreakCondition;
1631 m_sOperator = ">=";
1632 break;
1633
1634 case eBRLessThenEquals:
1635 m_pfnIsBreak = IsLessThenEqualsBreakCondition;
1636 m_sOperator = "<=";
1637 break;
1638
1639 default:
1640 assert(false);
1641 break;
1642 }
1643
1644 int regMask = (0x100 << (_cpu->register_size() - 1)) - 1;
1645
1646 if (break_mask == 0) {
1647 break_mask = regMask;
1648 }
1649 }
1650
1651
~BreakpointRegister_Value()1652 BreakpointRegister_Value::~BreakpointRegister_Value()
1653 {
1654 }
1655
1656
IsEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1657 bool BreakpointRegister_Value::IsEqualsBreakCondition(unsigned int uRegValue,
1658 unsigned int uRegMask, unsigned int uRegTestValue)
1659 {
1660 return (uRegValue & uRegMask) == uRegTestValue;
1661 }
1662
1663
IsNotEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1664 bool BreakpointRegister_Value::IsNotEqualsBreakCondition(unsigned int uRegValue,
1665 unsigned int uRegMask, unsigned int uRegTestValue)
1666 {
1667 return (uRegValue & uRegMask) != uRegTestValue;
1668 }
1669
1670
IsGreaterThenBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1671 bool BreakpointRegister_Value::IsGreaterThenBreakCondition(unsigned int uRegValue,
1672 unsigned int uRegMask, unsigned int uRegTestValue)
1673 {
1674 return (uRegValue & uRegMask) > uRegTestValue;
1675 }
1676
1677
IsLessThenBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1678 bool BreakpointRegister_Value::IsLessThenBreakCondition(unsigned int uRegValue,
1679 unsigned int uRegMask, unsigned int uRegTestValue)
1680 {
1681 return (uRegValue & uRegMask) < uRegTestValue;
1682 }
1683
1684
IsGreaterThenEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1685 bool BreakpointRegister_Value::IsGreaterThenEqualsBreakCondition(unsigned int uRegValue,
1686 unsigned int uRegMask, unsigned int uRegTestValue)
1687 {
1688 return (uRegValue & uRegMask) >= uRegTestValue;
1689 }
1690
1691
IsLessThenEqualsBreakCondition(unsigned int uRegValue,unsigned int uRegMask,unsigned int uRegTestValue)1692 bool BreakpointRegister_Value::IsLessThenEqualsBreakCondition(unsigned int uRegValue,
1693 unsigned int uRegMask, unsigned int uRegTestValue)
1694 {
1695 return (uRegValue & uRegMask) <= uRegTestValue;
1696 }
1697
1698
1699 /*
1700 void BreakpointRegister_Value::invokeAction()
1701 {
1702 if(eval_Expression())
1703 TriggerObject::invokeAction();
1704 }
1705 */
1706 /// BreakpointRegister_Value::print() - base class function
1707 /// would be unusual to not be over ridden.
print()1708 void BreakpointRegister_Value::print()
1709 {
1710 Register *pReg = getReg();
1711 std::string & sName = pReg->name();
1712 const char * pFormat = sName.empty()
1713 ? "%d: %s %s: break when register %s0x%x ANDed with 0x%x %s 0x%x\n"
1714 : "%d: %s %s: break when register %s(0x%x) ANDed with 0x%x %s 0x%x\n" ;
1715 GetUserInterface().DisplayMessage(pFormat,
1716 bpn, cpu->name().c_str(), bpName(),
1717 sName.c_str(), pReg->address, break_mask,
1718 m_sOperator.c_str(), break_value);
1719 TriggerObject::print();
1720 }
1721
1722
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)1723 int BreakpointRegister_Value::printTraced(Trace *pTrace, unsigned int tbi,
1724 char *pBuf, int szBuf)
1725
1726 {
1727 if (pBuf && pTrace) {
1728 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
1729 int m = snprintf(pBuf, szBuf, " read 0x%x from reg 0x%x", valueRead, address);
1730 return m > 0 ? m : 0;
1731 }
1732
1733 return 0;
1734 }
1735
1736
1737 //-------------------------------------------------------------------
1738 //
Break_register_write_value(Processor * _cpu,int _repl,int bp,unsigned int bv,unsigned int _operator,unsigned int bm)1739 Break_register_write_value::Break_register_write_value(Processor *_cpu,
1740 int _repl,
1741 int bp,
1742 unsigned int bv,
1743 unsigned int _operator,
1744 unsigned int bm) :
1745 BreakpointRegister_Value(_cpu, _repl, bp, bv, _operator, bm)
1746 {
1747 }
1748
1749
~Break_register_write_value()1750 Break_register_write_value::~Break_register_write_value()
1751 {
1752 }
1753
1754
takeAction()1755 void Break_register_write_value::takeAction()
1756 {
1757 trace.raw(m_brt->type(1) | (getReplaced()->get_value() & 0xffffff));
1758
1759 if (verbosity && verbosity->getVal()) {
1760 GetUserInterface().DisplayMessage(IDS_HIT_BREAK, bpn);
1761 std::string sFormattedRegAddress;
1762 sFormattedRegAddress = GetUserInterface().FormatRegisterAddress(getReg());
1763
1764 if (break_mask != m_uDefRegMask) {
1765 sFormattedRegAddress += " & ";
1766 sFormattedRegAddress += GetUserInterface().FormatLabeledValue("",
1767 break_mask);
1768 }
1769
1770 GetUserInterface().DisplayMessage(IDS_BREAK_WRITING_REG_OP_VALUE,
1771 sFormattedRegAddress.c_str(),
1772 m_sOperator.c_str(),
1773 break_value);
1774 }
1775
1776 bp.halt();
1777 }
1778
1779
1780 //========================================================================
1781 //
Break_register_read(Processor * _cpu,int _repl,int bp)1782 Break_register_read::Break_register_read(Processor *_cpu, int _repl, int bp):
1783 BreakpointRegister(_cpu, 0, _repl, bp)
1784 {
1785 }
1786
1787
~Break_register_read()1788 Break_register_read::~Break_register_read()
1789 {
1790 }
1791
1792
takeAction()1793 void Break_register_read::takeAction()
1794 {
1795 trace.raw(m_brt->type(1) | (getReplaced()->get_value() & 0xffffff));
1796
1797 if (verbosity && verbosity->getVal()) {
1798 GetUserInterface().DisplayMessage(IDS_HIT_BREAK, bpn);
1799 std::string sFormattedRegAddress;
1800 sFormattedRegAddress = GetUserInterface().FormatRegisterAddress(getReg());
1801 GetUserInterface().DisplayMessage(IDS_BREAK_READING_REG,
1802 sFormattedRegAddress.c_str());
1803 }
1804
1805 bp.halt();
1806 }
1807
1808
get()1809 unsigned int Break_register_read::get()
1810 {
1811 unsigned int v = getReplaced()->get();
1812 invokeAction();
1813 return v;
1814 }
1815
1816
getRV()1817 RegisterValue Break_register_read::getRV()
1818 {
1819 RegisterValue rv = getReplaced()->getRV();
1820 invokeAction();
1821 return rv;
1822 }
1823
1824
getRVN()1825 RegisterValue Break_register_read::getRVN()
1826 {
1827 RegisterValue rv = getReplaced()->getRVN();
1828 invokeAction();
1829 return rv;
1830 }
1831
1832
get_bit(unsigned int bit_number)1833 bool Break_register_read::get_bit(unsigned int bit_number)
1834 {
1835 invokeAction();
1836 return (getReplaced()->get_bit(bit_number));
1837 }
1838
1839
get_bit_voltage(unsigned int bit_number)1840 double Break_register_read::get_bit_voltage(unsigned int bit_number)
1841 {
1842 return getReplaced()->get_bit_voltage(bit_number);
1843 }
1844
1845
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)1846 int Break_register_read::printTraced(Trace *pTrace, unsigned int tbi,
1847 char *pBuf, int szBuf)
1848
1849 {
1850 if (pBuf && pTrace) {
1851 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
1852 int m = snprintf(pBuf, szBuf, " read 0x%x from reg 0x%x", valueRead, address);
1853 return m > 0 ? m : 0;
1854 }
1855
1856 return 0;
1857 }
1858
1859
1860 //========================================================================
1861 //
Break_register_write(Processor * _cpu,int _repl,int bp)1862 Break_register_write::Break_register_write(Processor *_cpu, int _repl, int bp):
1863 BreakpointRegister(_cpu, 0, _repl, bp)
1864 {
1865 }
1866
1867
~Break_register_write()1868 Break_register_write::~Break_register_write()
1869 {
1870 }
1871
1872
takeAction()1873 void Break_register_write::takeAction()
1874 {
1875 trace.raw(m_brt->type(1) | (getReplaced()->get_value() & 0xffffff));
1876
1877 if (verbosity && verbosity->getVal()) {
1878 GetUserInterface().DisplayMessage(IDS_HIT_BREAK, bpn);
1879 std::string sFormattedRegAddress;
1880 sFormattedRegAddress = GetUserInterface().FormatRegisterAddress(
1881 address, 0);
1882 GetUserInterface().DisplayMessage(IDS_BREAK_WRITING_REG,
1883 sFormattedRegAddress.c_str());
1884 }
1885
1886 bp.halt();
1887 }
1888
1889
put(unsigned int new_value)1890 void Break_register_write::put(unsigned int new_value)
1891 {
1892 getReplaced()->put(new_value);
1893 invokeAction();
1894 }
1895
1896
putRV(RegisterValue rv)1897 void Break_register_write::putRV(RegisterValue rv)
1898 {
1899 getReplaced()->putRV(rv);
1900 invokeAction();
1901 }
1902
1903
setbit(unsigned int bit_number,bool new_value)1904 void Break_register_write::setbit(unsigned int bit_number, bool new_value)
1905 {
1906 getReplaced()->setbit(bit_number, new_value);
1907 invokeAction();
1908 }
1909
1910
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)1911 int Break_register_write::printTraced(Trace *pTrace, unsigned int tbi,
1912 char *pBuf, int szBuf)
1913 {
1914 if (pBuf && pTrace) {
1915 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
1916 int m = snprintf(pBuf, szBuf, " wrote 0x%x to reg 0x%x", valueRead, address);
1917 return m > 0 ? m : 0;
1918 }
1919
1920 return 0;
1921 }
1922
1923
1924 //========================================================================
Break_register_read_value(Processor * _cpu,int _repl,int bp,unsigned int bv,unsigned int _operator,unsigned int bm)1925 Break_register_read_value::Break_register_read_value(Processor *_cpu,
1926 int _repl,
1927 int bp,
1928 unsigned int bv,
1929 unsigned int _operator,
1930 unsigned int bm) :
1931 BreakpointRegister_Value(_cpu, _repl, bp, bv, _operator, bm)
1932 {
1933 }
1934
1935
~Break_register_read_value()1936 Break_register_read_value::~Break_register_read_value()
1937 {
1938 }
1939
1940
takeAction()1941 void Break_register_read_value::takeAction()
1942 {
1943 trace.raw(m_brt->type(1) | (getReplaced()->get_value() & 0xffffff));
1944
1945 if (verbosity && verbosity->getVal()) {
1946 GetUserInterface().DisplayMessage(IDS_HIT_BREAK, bpn);
1947 std::string sFormattedRegAddress;
1948 sFormattedRegAddress = GetUserInterface().FormatRegisterAddress(getReg());
1949
1950 if (break_mask != m_uDefRegMask) {
1951 sFormattedRegAddress += " & ";
1952 sFormattedRegAddress += GetUserInterface().FormatLabeledValue("",
1953 break_mask);
1954 }
1955
1956 GetUserInterface().DisplayMessage(IDS_BREAK_READING_REG_OP_VALUE,
1957 sFormattedRegAddress.c_str(),
1958 m_sOperator.c_str(),
1959 break_value);
1960 }
1961
1962 bp.halt();
1963 }
1964
1965
get()1966 unsigned int Break_register_read_value::get()
1967 {
1968 unsigned int v = getReplaced()->get();
1969
1970 if (m_pfnIsBreak(v, break_mask, break_value)) {
1971 invokeAction();
1972 }
1973
1974 return v;
1975 }
1976
1977
getRV()1978 RegisterValue Break_register_read_value::getRV()
1979 {
1980 RegisterValue v = getReplaced()->getRV();
1981
1982 if (m_pfnIsBreak(v.data, break_mask, break_value)) {
1983 invokeAction();
1984 }
1985
1986 return v;
1987 }
1988
1989
getRVN()1990 RegisterValue Break_register_read_value::getRVN()
1991 {
1992 RegisterValue v = getReplaced()->getRVN();
1993
1994 if (m_pfnIsBreak(v.data, break_mask, break_value)) {
1995 invokeAction();
1996 }
1997
1998 return v;
1999 }
2000
2001
get_bit(unsigned int bit_number)2002 bool Break_register_read_value::get_bit(unsigned int bit_number)
2003 {
2004 unsigned int v = getReplaced()->get();
2005 unsigned int mask = 1 << (bit_number & 7);
2006
2007 if ((break_mask & mask) && (v & mask) == (break_value & mask)) {
2008 invokeAction();
2009 }
2010
2011 return getReplaced()->get_bit(bit_number);
2012 }
2013
2014
get_bit_voltage(unsigned int bit_number)2015 double Break_register_read_value::get_bit_voltage(unsigned int bit_number)
2016 {
2017 return getReplaced()->get_bit_voltage(bit_number);
2018 }
2019
2020
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)2021 int Break_register_read_value::printTraced(Trace *pTrace, unsigned int tbi,
2022 char *pBuf, int szBuf)
2023
2024 {
2025 if (pBuf && pTrace) {
2026 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
2027 int m = snprintf(pBuf, szBuf, " read 0x%x from reg 0x%x", valueRead, address);
2028 return m > 0 ? m : 0;
2029 }
2030
2031 return 0;
2032 }
2033
2034
2035 //========================================================================
2036
2037
put(unsigned int new_value)2038 void Break_register_write_value::put(unsigned int new_value)
2039 {
2040 getReplaced()->put(new_value);
2041
2042 if (m_pfnIsBreak(new_value, break_mask, break_value)) {
2043 invokeAction();
2044 }
2045 }
2046
2047
putRV(RegisterValue rv)2048 void Break_register_write_value::putRV(RegisterValue rv)
2049 {
2050 getReplaced()->putRV(rv);
2051
2052 if (m_pfnIsBreak(rv.data, break_mask, break_value)) {
2053 invokeAction();
2054 }
2055 }
2056
2057
setbit(unsigned int bit_number,bool new_bit)2058 void Break_register_write_value::setbit(unsigned int bit_number, bool new_bit)
2059 {
2060 int val_mask = 1 << bit_number;
2061 int new_value = ((int)new_bit) << bit_number;
2062 getReplaced()->setbit(bit_number, new_value ? true : false);
2063
2064 if ((val_mask & break_mask) &&
2065 (((getReplaced()->value.get() & ~val_mask) // clear the old bit
2066 | new_value) // set the new bit
2067 & break_mask) == break_value) {
2068 invokeAction();
2069 }
2070 }
2071
2072
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)2073 int Break_register_write_value::printTraced(Trace *pTrace, unsigned int tbi,
2074 char *pBuf, int szBuf)
2075
2076 {
2077 if (pBuf && pTrace) {
2078 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
2079 int m = snprintf(pBuf, szBuf, " wrote 0x%x to reg 0x%x", valueRead, address);
2080 return m > 0 ? m : 0;
2081 }
2082
2083 return 0;
2084 }
2085
2086
2087 //========================================================================
2088 //
Break_register_change(Processor * _cpu,int _repl,int bp)2089 Break_register_change::Break_register_change(Processor *_cpu, int _repl, int bp):
2090 BreakpointRegister(_cpu, 0, _repl, bp)
2091 {
2092 }
2093
2094
~Break_register_change()2095 Break_register_change::~Break_register_change()
2096 {
2097 }
2098
2099
takeAction()2100 void Break_register_change::takeAction()
2101 {
2102 trace.raw(m_brt->type(1) | (getReplaced()->get_value() & 0xffffff));
2103
2104 if (verbosity && verbosity->getVal()) {
2105 GetUserInterface().DisplayMessage(IDS_HIT_BREAK, bpn);
2106 std::string sFormattedRegAddress;
2107 sFormattedRegAddress = GetUserInterface().FormatRegisterAddress(
2108 address, 0);
2109 GetUserInterface().DisplayMessage(IDS_BREAK_WRITING_REG,
2110 sFormattedRegAddress.c_str());
2111 }
2112
2113 bp.halt();
2114 }
2115
2116
put(unsigned int new_value)2117 void Break_register_change::put(unsigned int new_value)
2118 {
2119 unsigned int before = getReplaced()->get_value();
2120 getReplaced()->put(new_value);
2121
2122 if (before != getReplaced()->get_value()) {
2123 invokeAction();
2124 }
2125 }
2126
2127
putRV(RegisterValue rv)2128 void Break_register_change::putRV(RegisterValue rv)
2129 {
2130 RegisterValue before = getReplaced()->getRV_notrace();
2131 getReplaced()->putRV(rv);
2132
2133 if (before != getReplaced()->getRV_notrace()) {
2134 invokeAction();
2135 }
2136 }
2137
2138
setbit(unsigned int bit_number,bool new_value)2139 void Break_register_change::setbit(unsigned int bit_number, bool new_value)
2140 {
2141 bool before = getReplaced()->get_bit(bit_number);
2142 getReplaced()->setbit(bit_number, new_value);
2143
2144 if (before != getReplaced()->get_bit(bit_number)) {
2145 invokeAction();
2146 }
2147 }
2148
2149
printTraced(Trace * pTrace,unsigned int tbi,char * pBuf,int szBuf)2150 int Break_register_change::printTraced(Trace *pTrace, unsigned int tbi,
2151 char *pBuf, int szBuf)
2152
2153 {
2154 if (pBuf && pTrace) {
2155 unsigned int valueRead = pTrace->get(tbi + 1) & 0xffff;
2156 int m = snprintf(pBuf, szBuf, " wrote 0x%x to reg 0x%x", valueRead, address);
2157 return m > 0 ? m : 0;
2158 }
2159
2160 return 0;
2161 }
2162
2163
2164 //========================================================================
2165 //------------------------------------------------------------------------
2166 // CommandAssertion
2167 //
2168 // Associates a gpsim command with an instruction. I.e. when the simulated
2169 // instruction is executed, the gpsim command will execute first and then
2170 // the instruction is simulated.
2171
2172
CommandAssertion(Processor * new_cpu,unsigned int instAddress,unsigned int bp,const char * _command,bool _bPostAssertion)2173 CommandAssertion::CommandAssertion(Processor *new_cpu,
2174 unsigned int instAddress,
2175 unsigned int bp,
2176 const char *_command,
2177 bool _bPostAssertion)
2178 : Breakpoint_Instruction(new_cpu, instAddress, bp), bPostAssertion(_bPostAssertion)
2179 {
2180 size_t len = strlen(_command);
2181 command = new char[len + 3];
2182 strcpy(command, _command);
2183 command[len] = '\n';
2184 command[len + 1] = 0;
2185 command[len + 2] = 0;
2186 }
2187
2188
~CommandAssertion()2189 CommandAssertion::~CommandAssertion()
2190 {
2191 delete [] command;
2192 }
2193
2194
execute()2195 void CommandAssertion::execute()
2196 {
2197 if (bPostAssertion && getReplaced()) {
2198 getReplaced()->execute();
2199 }
2200
2201 //printf("execute command: %s -- post = %s\n",command,(bPostAssertion?"true":"false"));
2202 ICommandHandler *pCli = CCommandManager::GetManager().find("gpsimCLI");
2203
2204 if (pCli) {
2205 pCli->Execute(command, 0);
2206 }
2207
2208 if (!bPostAssertion && getReplaced()) {
2209 getReplaced()->execute();
2210 }
2211 }
2212
2213
2214 //------------------------------------------------------------------------------
print()2215 void CommandAssertion::print()
2216 {
2217 Breakpoint_Instruction::print();
2218 std::cout << " execute command " << command << '\n';
2219 }
2220
2221
printTraced(Trace *,unsigned int,char *,int)2222 int CommandAssertion::printTraced(Trace * , unsigned int /* tbi */ ,
2223 char * /* pBuf */ , int /* szBuf */ )
2224 {
2225 return 0;
2226 }
2227
2228
2229 //============================================================================
2230
put(unsigned int new_value)2231 void Log_Register_Write::put(unsigned int new_value)
2232 {
2233 getReplaced()->put(new_value);
2234 takeAction();
2235 }
2236
2237
setbit(unsigned int bit_number,bool new_value)2238 void Log_Register_Write::setbit(unsigned int bit_number, bool new_value)
2239 {
2240 getReplaced()->setbit(bit_number, new_value);
2241 takeAction();
2242 }
2243
2244
takeAction()2245 void Log_Register_Write::takeAction()
2246 {
2247 GetTraceLog().register_write(getReg(),
2248 get_cycles().get());
2249 }
2250
2251
takeAction()2252 void Log_Register_Write_value::takeAction()
2253 {
2254 GetTraceLog().register_write_value(getReg(),
2255 get_cycles().get());
2256 }
2257
2258
get()2259 unsigned int Log_Register_Read::get()
2260 {
2261 unsigned int v = getReplaced()->get();
2262 takeAction();
2263 return v;
2264 }
2265
2266
getRV()2267 RegisterValue Log_Register_Read::getRV()
2268 {
2269 RegisterValue rv = getReplaced()->getRV();
2270 takeAction();
2271 return rv;
2272 }
2273
2274
getRVN()2275 RegisterValue Log_Register_Read::getRVN()
2276 {
2277 RegisterValue rv = getReplaced()->getRVN();
2278 takeAction();
2279 return rv;
2280 }
2281
2282
get_bit(unsigned int bit_number)2283 bool Log_Register_Read::get_bit(unsigned int bit_number)
2284 {
2285 takeAction();
2286 return (getReplaced()->get_bit(bit_number));
2287 }
2288
2289
takeAction()2290 void Log_Register_Read::takeAction()
2291 {
2292 GetTraceLog().register_read(getReg(),
2293 get_cycles().get());
2294 }
2295
2296
takeAction()2297 void Log_Register_Read_value::takeAction()
2298 {
2299 GetTraceLog().register_read(getReg(),
2300 get_cycles().get());
2301 }
2302