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