DataBreakPoint.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99: package xeij;
100:
101: import java.awt.*;
102: import java.awt.event.*;
103: import java.lang.*;
104: import java.util.*;
105: import javax.swing.*;
106: import javax.swing.event.*;
107:
108: public class DataBreakPoint {
109:
110: public static final boolean DBP_ON = true;
111:
112:
113: public static final int DBP_BYTE = 0;
114: public static final int DBP_WORD = 1;
115: public static final int DBP_LONG = 2;
116: public static final java.util.List<String> DBP_SIZE_LIST_EN = Arrays.asList ("Byte", "Word", "Long");
117: public static final java.util.List<String> DBP_SIZE_LIST_JA = Arrays.asList ("バイト", "ワード", "ロング");
118:
119:
120: public static final MemoryMappedDevice[] dbpUserMap = DBP_ON ? new MemoryMappedDevice[XEiJ.BUS_PAGE_COUNT] : null;
121: public static final MemoryMappedDevice[] dbpSuperMap = DBP_ON ? new MemoryMappedDevice[XEiJ.BUS_PAGE_COUNT] : null;
122: public static MemoryMappedDevice[] dbpMemoryMap;
123:
124:
125: public static ArrayList<DataBreakRecord> dbpList;
126:
127:
128: public static int dbpLock;
129: public static JFrame dbpFrame;
130: public static GridLayout dbpListGridLayout;
131: public static JPanel dbpListPanel;
132:
133:
134:
135: public static void dbpInit () {
136:
137: Arrays.fill (dbpUserMap, MemoryMappedDevice.MMD_NUL);
138: Arrays.fill (dbpSuperMap, MemoryMappedDevice.MMD_NUL);
139: dbpMemoryMap = dbpSuperMap;
140:
141:
142: dbpList = new ArrayList<DataBreakRecord> ();
143:
144: }
145:
146:
147: public static void dbpStart () {
148: if (RestorableFrame.rfmGetOpened (Settings.SGS_DBP_FRAME_KEY)) {
149: dbpOpen ();
150: }
151: }
152:
153:
154:
155: public static void dbpOpen () {
156: if (dbpFrame == null) {
157: dbpMakeFrame ();
158: }
159: XEiJ.dbgVisibleMask |= XEiJ.DBG_DBP_VISIBLE_MASK;
160: dbpFrame.setVisible (true);
161: }
162:
163:
164:
165:
166: public static void dbpMakeFrame () {
167: dbpLock = 0;
168:
169: ActionListener listener = new ActionListener () {
170: @Override public void actionPerformed (ActionEvent ae) {
171: Object source = ae.getSource ();
172: switch (ae.getActionCommand ()) {
173: case "Add":
174: new DataBreakRecord (0x00000000, DBP_BYTE, 0xff, 0, 0xff, false, 0, 0);
175: break;
176: }
177: }
178: };
179:
180: dbpListGridLayout = new GridLayout (1, 9);
181: dbpListPanel = ComponentFactory.addComponents (
182: new JPanel (dbpListGridLayout),
183: Multilingual.mlnText (ComponentFactory.createLabel ("Enabled"), "ja", "有効"),
184: Multilingual.mlnText (ComponentFactory.createLabel ("Address"), "ja", "アドレス"),
185: Multilingual.mlnText (ComponentFactory.createLabel ("Size"), "ja", "サイズ"),
186: Multilingual.mlnText (ComponentFactory.createLabel ("Mask"), "ja", "マスク"),
187: Multilingual.mlnText (ComponentFactory.createLabel ("Lower"), "ja", "下限"),
188: Multilingual.mlnText (ComponentFactory.createLabel ("Upper"), "ja", "上限"),
189: Multilingual.mlnText (ComponentFactory.createLabel ("Count"), "ja", "回数"),
190: Multilingual.mlnText (ComponentFactory.createLabel ("Threshold"), "ja", "閾値"),
191: Multilingual.mlnText (ComponentFactory.createLabel ("Remove"), "ja", "削除")
192: );
193: dbpFrame = Multilingual.mlnTitle (
194: ComponentFactory.createRestorableSubFrame (
195: Settings.SGS_DBP_FRAME_KEY,
196: "Data break point",
197: null,
198: ComponentFactory.setPreferredSize (
199: ComponentFactory.createBorderPanel (
200:
201: ComponentFactory.createScrollPane (dbpListPanel),
202:
203: null,
204:
205: null,
206:
207: ComponentFactory.createFlowPanel (
208: FlowLayout.CENTER,
209: Multilingual.mlnText (ComponentFactory.createButton ("Add", listener), "ja", "追加")
210: )
211:
212: ),
213: 750, 100)
214: ),
215: "ja", "データブレークポイント");
216:
217: ComponentFactory.addListener (
218: dbpFrame,
219: new WindowAdapter () {
220: @Override public void windowClosing (WindowEvent we) {
221: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_DBP_VISIBLE_MASK;
222: }
223: });
224: }
225:
226:
227:
228:
229:
230:
231: public static void dbpBreak (int size, int address, int data) {
232: if (size == DBP_BYTE) {
233: for (DataBreakRecord r : dbpList) {
234: if (r.dbrEnabled) {
235: if (r.dbrSize == DBP_BYTE) {
236: if (address == r.dbrAddress) {
237: int masked = data & r.dbrMask;
238: if (r.dbrLower <= r.dbrUpper ?
239: r.dbrLower <= masked && masked <= r.dbrUpper :
240: masked <= r.dbrUpper || r.dbrLower <= masked) {
241: r.dbrSetCount (r.dbrCount + 1);
242: if (r.dbrThreshold <= r.dbrCount) {
243: XEiJ.mpuStop (null);
244: }
245: }
246: }
247: }
248: }
249: }
250: } else if (size == DBP_WORD) {
251: for (DataBreakRecord r : dbpList) {
252: if (r.dbrEnabled) {
253: if (r.dbrSize == DBP_BYTE) {
254: if (address == r.dbrAddress) {
255: int masked = data >>> 8 & r.dbrMask;
256: if (r.dbrLower <= r.dbrUpper ?
257: r.dbrLower <= masked && masked <= r.dbrUpper :
258: masked <= r.dbrUpper || r.dbrLower <= masked) {
259: r.dbrSetCount (r.dbrCount + 1);
260: if (r.dbrThreshold <= r.dbrCount) {
261: XEiJ.mpuStop (null);
262: }
263: }
264: } else if (address + 1 == r.dbrAddress) {
265: int masked = data & r.dbrMask;
266: if (r.dbrLower <= r.dbrUpper ?
267: r.dbrLower <= masked && masked <= r.dbrUpper :
268: masked <= r.dbrUpper || r.dbrLower <= masked) {
269: r.dbrSetCount (r.dbrCount + 1);
270: if (r.dbrThreshold <= r.dbrCount) {
271: XEiJ.mpuStop (null);
272: }
273: }
274: }
275: } else if (r.dbrSize == DBP_WORD) {
276: if (address == r.dbrAddress) {
277: int masked = data & r.dbrMask;
278: if (r.dbrLower <= r.dbrUpper ?
279: r.dbrLower <= masked && masked <= r.dbrUpper :
280: masked <= r.dbrUpper || r.dbrLower <= masked) {
281: r.dbrSetCount (r.dbrCount + 1);
282: if (r.dbrThreshold <= r.dbrCount) {
283: XEiJ.mpuStop (null);
284: }
285: }
286: }
287: }
288: }
289: }
290: } else if (size == DBP_LONG) {
291: for (DataBreakRecord r : dbpList) {
292: if (r.dbrEnabled) {
293: if (r.dbrSize == DBP_BYTE) {
294: if (address == r.dbrAddress) {
295: int masked = data >>> 24 & r.dbrMask;
296: if (r.dbrLower <= r.dbrUpper ?
297: r.dbrLower <= masked && masked <= r.dbrUpper :
298: masked <= r.dbrUpper || r.dbrLower <= masked) {
299: r.dbrSetCount (r.dbrCount + 1);
300: if (r.dbrThreshold <= r.dbrCount) {
301: XEiJ.mpuStop (null);
302: }
303: }
304: } else if (address + 1 == r.dbrAddress) {
305: int masked = data >>> 16 & r.dbrMask;
306: if (r.dbrLower <= r.dbrUpper ?
307: r.dbrLower <= masked && masked <= r.dbrUpper :
308: masked <= r.dbrUpper || r.dbrLower <= masked) {
309: r.dbrSetCount (r.dbrCount + 1);
310: if (r.dbrThreshold <= r.dbrCount) {
311: XEiJ.mpuStop (null);
312: }
313: }
314: } else if (address + 2 == r.dbrAddress) {
315: int masked = data >>> 8 & r.dbrMask;
316: if (r.dbrLower <= r.dbrUpper ?
317: r.dbrLower <= masked && masked <= r.dbrUpper :
318: masked <= r.dbrUpper || r.dbrLower <= masked) {
319: r.dbrSetCount (r.dbrCount + 1);
320: if (r.dbrThreshold <= r.dbrCount) {
321: XEiJ.mpuStop (null);
322: }
323: }
324: } else if (address + 3 == r.dbrAddress) {
325: int masked = data & r.dbrMask;
326: if (r.dbrLower <= r.dbrUpper ?
327: r.dbrLower <= masked && masked <= r.dbrUpper :
328: masked <= r.dbrUpper || r.dbrLower <= masked) {
329: r.dbrSetCount (r.dbrCount + 1);
330: if (r.dbrThreshold <= r.dbrCount) {
331: XEiJ.mpuStop (null);
332: }
333: }
334: }
335: } else if (r.dbrSize == DBP_WORD) {
336: if (address == r.dbrAddress) {
337: int masked = data >> 16 & r.dbrMask;
338: if (r.dbrLower <= r.dbrUpper ?
339: r.dbrLower <= masked && masked <= r.dbrUpper :
340: masked <= r.dbrUpper || r.dbrLower <= masked) {
341: r.dbrSetCount (r.dbrCount + 1);
342: if (r.dbrThreshold <= r.dbrCount) {
343: XEiJ.mpuStop (null);
344: }
345: }
346: } else if (address + 2 == r.dbrAddress) {
347: int masked = data & r.dbrMask;
348: if (r.dbrLower <= r.dbrUpper ?
349: r.dbrLower <= masked && masked <= r.dbrUpper :
350: masked <= r.dbrUpper || r.dbrLower <= masked) {
351: r.dbrSetCount (r.dbrCount + 1);
352: if (r.dbrThreshold <= r.dbrCount) {
353: XEiJ.mpuStop (null);
354: }
355: }
356: }
357: } else if (r.dbrSize == DBP_LONG) {
358: if (address == r.dbrAddress) {
359: int masked = data & r.dbrMask;
360: if (Integer.compareUnsigned (r.dbrLower, r.dbrUpper) <= 0 ?
361: Integer.compareUnsigned (r.dbrLower, masked) <= 0 && Integer.compareUnsigned (masked, r.dbrUpper) <= 0 :
362: Integer.compareUnsigned (masked, r.dbrUpper) <= 0 || Integer.compareUnsigned (r.dbrLower, masked) <= 0) {
363: r.dbrSetCount (r.dbrCount + 1);
364: if (r.dbrThreshold <= r.dbrCount) {
365: XEiJ.mpuStop (null);
366: }
367: }
368: }
369: }
370: }
371: }
372: }
373: }
374:
375:
376:
377: public static class DataBreakRecord implements Comparable<DataBreakRecord> {
378:
379:
380: public int dbrAddress;
381: public int dbrSize;
382: public int dbrMask;
383: public int dbrLower;
384: public int dbrUpper;
385:
386:
387: public boolean dbrEnabled;
388: public int dbrCount;
389: public int dbrThreshold;
390:
391:
392: public Box dbrEnabledBox;
393: public JCheckBox dbrEnabledCheckBox;
394: public Hex8Spinner dbrAddressSpinner;
395: public JSpinner dbrSizeSpinner;
396: public JLabel[] dbrSizeLabels;
397: public Hex8Spinner dbrMaskSpinner;
398: public Hex8Spinner dbrLowerSpinner;
399: public Hex8Spinner dbrUpperSpinner;
400: public JSpinner dbrCountSpinner;
401: public SpinnerNumberModel dbrCountModel;
402: public JSpinner dbrThresholdSpinner;
403: public SpinnerNumberModel dbrThresholdModel;
404: public Box dbrRemoveBox;
405: public JButton dbrRemoveButton;
406:
407:
408: @Override public int compareTo (DataBreakRecord r) {
409: int t = Integer.compareUnsigned (dbrAddress, r.dbrAddress);
410: if (t == 0) {
411: t = Integer.compareUnsigned (dbrSize, r.dbrSize);
412: if (t == 0) {
413: t = Integer.compareUnsigned (dbrMask, r.dbrMask);
414: if (t == 0) {
415: t = Integer.compareUnsigned (dbrLower, r.dbrLower);
416: if (t == 0) {
417: t = Integer.compareUnsigned (dbrUpper, r.dbrUpper);
418: }
419: }
420: }
421: }
422: return t;
423: }
424:
425:
426:
427: @SuppressWarnings ("this-escape") public DataBreakRecord (int address, int size, int mask, int lower, int upper, boolean enabled, int count, int threshold) {
428:
429:
430: mask &= size == DBP_BYTE ? 0xff : size == DBP_WORD ? 0xffff : 0xffffffff;
431: lower &= mask;
432: upper &= mask;
433:
434:
435: dbrAddress = address;
436: dbrSize = size;
437: dbrMask = mask;
438: dbrLower = lower;
439: dbrUpper = upper;
440:
441:
442: dbrEnabled = enabled;
443: dbrCount = count;
444: dbrThreshold = threshold;
445:
446:
447: ActionListener listener = new ActionListener () {
448: @Override public void actionPerformed (ActionEvent ae) {
449: Object source = ae.getSource ();
450: switch (ae.getActionCommand ()) {
451: case "Enabled":
452: dbrSetEnabled (((JCheckBox) source).isSelected ());
453: break;
454: case "Remove":
455: dbrRemove ();
456: break;
457: }
458: }
459: };
460:
461:
462: dbrEnabledBox = ComponentFactory.createGlueBox (
463: dbrEnabledCheckBox = Multilingual.mlnText (ComponentFactory.createCheckBox (dbrEnabled, "Enabled", listener), "ja", "有効")
464: );
465:
466:
467: dbrAddressSpinner = ComponentFactory.createHex8Spinner (dbrAddress, 0xffffffff, false, new ChangeListener () {
468: @Override public void stateChanged (ChangeEvent ce) {
469: if (dbpLock == 0) {
470: dbrSetAddress (((Hex8Spinner) ce.getSource ()).getIntValue ());
471: }
472: }
473: });
474:
475:
476: dbrSizeSpinner = Multilingual.mlnList (
477: ComponentFactory.createListSpinner (
478: DBP_SIZE_LIST_EN,
479: DBP_SIZE_LIST_EN.get (dbrSize),
480: new ChangeListener () {
481: @Override public void stateChanged (ChangeEvent ce) {
482: if (dbpLock == 0) {
483: SpinnerListModel model = (SpinnerListModel) ((JSpinner) ce.getSource ()).getModel ();
484: dbrSetSize (model.getList ().indexOf (model.getValue ()));
485: }
486: }
487: }),
488: "ja", DBP_SIZE_LIST_JA);
489:
490:
491: dbrMaskSpinner = ComponentFactory.createHex8Spinner (dbrMask, -1, false, new ChangeListener () {
492: @Override public void stateChanged (ChangeEvent ce) {
493: if (dbpLock == 0) {
494: dbrSetMask (((Hex8Spinner) ce.getSource ()).getIntValue ());
495: }
496: }
497: });
498:
499:
500: dbrLowerSpinner = ComponentFactory.createHex8Spinner (dbrLower, -1, false, new ChangeListener () {
501: @Override public void stateChanged (ChangeEvent ce) {
502: if (dbpLock == 0) {
503: dbrSetLower (((Hex8Spinner) ce.getSource ()).getIntValue ());
504: }
505: }
506: });
507:
508:
509: dbrUpperSpinner = ComponentFactory.createHex8Spinner (dbrUpper, -1, false, new ChangeListener () {
510: @Override public void stateChanged (ChangeEvent ce) {
511: if (dbpLock == 0) {
512: dbrSetUpper (((Hex8Spinner) ce.getSource ()).getIntValue ());
513: }
514: }
515: });
516:
517:
518: dbrCountSpinner = ComponentFactory.createNumberSpinner (
519: dbrCountModel = new SpinnerNumberModel (dbrCount, 0, 99999999, 1),
520: 8,
521: new ChangeListener () {
522: @Override public void stateChanged (ChangeEvent ce) {
523: if (dbpLock == 0) {
524: dbrSetCount (dbrCountModel.getNumber ().intValue ());
525: }
526: }
527: });
528:
529:
530: dbrThresholdSpinner = ComponentFactory.createNumberSpinner (
531: dbrThresholdModel = new SpinnerNumberModel (dbrThreshold, 0, 99999999, 1),
532: 8,
533: new ChangeListener () {
534: @Override public void stateChanged (ChangeEvent ce) {
535: if (dbpLock == 0) {
536: dbrSetThreshold (dbrThresholdModel.getNumber ().intValue ());
537: }
538: }
539: });
540:
541:
542: dbrRemoveBox = ComponentFactory.createGlueBox (
543: dbrRemoveButton = Multilingual.mlnText (ComponentFactory.createButton ("Remove", listener), "ja", "削除")
544: );
545:
546:
547: dbpList.add (this);
548:
549:
550: dbpListGridLayout.setRows (dbpListGridLayout.getRows () + 1);
551: ComponentFactory.addComponents (
552: dbpListPanel,
553: dbrEnabledBox,
554: dbrAddressSpinner,
555: dbrSizeSpinner,
556: dbrMaskSpinner,
557: dbrLowerSpinner,
558: dbrUpperSpinner,
559: dbrCountSpinner,
560: dbrThresholdSpinner,
561: dbrRemoveBox
562: );
563: dbpListPanel.validate ();
564: dbpListPanel.repaint ();
565:
566:
567: dbrSetEnabled (dbrEnabled);
568:
569: }
570:
571:
572:
573: public void dbrRemove () {
574:
575:
576: dbrSetEnabled (false);
577:
578:
579: ComponentFactory.removeComponents (
580: dbpListPanel,
581: dbrEnabledBox,
582: dbrAddressSpinner,
583: dbrSizeSpinner,
584: dbrMaskSpinner,
585: dbrLowerSpinner,
586: dbrUpperSpinner,
587: dbrCountSpinner,
588: dbrThresholdSpinner,
589: dbrRemoveBox
590: );
591: dbpListGridLayout.setRows (dbpListGridLayout.getRows () - 1);
592: dbpListPanel.validate ();
593: dbpListPanel.repaint ();
594:
595:
596: dbpList.remove (this);
597:
598: }
599:
600:
601:
602: public void dbrSetAddress (int address) {
603: if (dbrAddress != address) {
604: dbrAddress = address;
605: if (dbrAddressSpinner != null) {
606: dbpLock++;
607: dbrAddressSpinner.setIntValue (address);
608: dbpLock--;
609: }
610: }
611: }
612:
613:
614:
615: public void dbrSetSize (int size) {
616: if (dbrSize != size) {
617: dbrSize = size;
618: if (dbrSizeSpinner != null) {
619: dbpLock++;
620: dbrSizeSpinner.setValue (((SpinnerListModel) dbrSizeSpinner.getModel ()).getList ().get (size));
621: dbpLock--;
622: }
623: dbrSetMask (dbrMask & (dbrSize == DBP_BYTE ? 0xff : dbrSize == DBP_WORD ? 0xffff : 0xffffffff));
624: }
625: }
626:
627:
628:
629: public void dbrSetMask (int mask) {
630: mask &= dbrSize == DBP_BYTE ? 0xff : dbrSize == DBP_WORD ? 0xffff : 0xffffffff;
631: if (dbrMask != mask) {
632: dbrMask = mask;
633: if (dbrMaskSpinner != null) {
634: dbpLock++;
635: dbrMaskSpinner.setIntValue (mask);
636: dbpLock--;
637: }
638: dbrSetLower (dbrLower);
639: dbrSetUpper (dbrUpper);
640: }
641: }
642:
643:
644:
645: public void dbrSetLower (int lower) {
646: lower &= dbrMask;
647: if (dbrLower != lower) {
648: dbrLower = lower;
649: if (dbrLowerSpinner != null) {
650: dbpLock++;
651: dbrLowerSpinner.setIntValue (lower);
652: dbpLock--;
653: }
654: }
655: }
656:
657:
658:
659: public void dbrSetUpper (int upper) {
660: upper &= dbrMask;
661: if (dbrUpper != upper) {
662: dbrUpper = upper;
663: if (dbrUpperSpinner != null) {
664: dbpLock++;
665: dbrUpperSpinner.setIntValue (upper);
666: dbpLock--;
667: }
668: }
669: }
670:
671:
672:
673: public void dbrSetEnabled (boolean enabled) {
674: if (dbrEnabled != enabled) {
675: dbrEnabled = enabled;
676: dbrEnabledCheckBox.setSelected (enabled);
677: }
678: int p = dbrAddress >>> XEiJ.BUS_PAGE_BITS;
679: if (dbrEnabled) {
680:
681: dbpUserMap[p] = dbpSuperMap[p] = MemoryMappedDevice.MMD_DBP;
682: } else {
683:
684: boolean exists = false;
685: for (DataBreakRecord r : dbpList) {
686: if (r.dbrAddress >>> XEiJ.BUS_PAGE_BITS == p) {
687: exists = true;
688: break;
689: }
690: }
691: dbpUserMap[p] = exists ? MemoryMappedDevice.MMD_DBP : XEiJ.busUserMap[p];
692: dbpSuperMap[p] = exists ? MemoryMappedDevice.MMD_DBP : XEiJ.busSuperMap[p];
693: }
694: }
695:
696:
697:
698: public void dbrSetCount (int count) {
699: if (dbrCount != count) {
700: dbrCount = count;
701: if (dbrCountSpinner != null) {
702: dbpLock++;
703: dbrCountSpinner.setValue (Integer.valueOf (count));
704: dbpLock--;
705: }
706: }
707: }
708:
709:
710:
711: public void dbrSetThreshold (int threshold) {
712: if (dbrThreshold != threshold) {
713: dbrThreshold = threshold;
714: if (dbrThresholdSpinner != null) {
715: dbpLock++;
716: dbrThresholdSpinner.setValue (Integer.valueOf (threshold));
717: dbpLock--;
718: }
719: }
720: }
721:
722: }
723:
724:
725:
726: }
727:
728:
729: