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: XEiJ.pnlExitFullScreen (false);
161: dbpFrame.setVisible (true);
162: }
163:
164:
165:
166:
167: public static void dbpMakeFrame () {
168: dbpLock = 0;
169:
170: ActionListener listener = new ActionListener () {
171: @Override public void actionPerformed (ActionEvent ae) {
172: Object source = ae.getSource ();
173: switch (ae.getActionCommand ()) {
174: case "Add":
175: new DataBreakRecord (0x00000000, DBP_BYTE, 0xff, 0, 0xff, true, true, false, 0, 0);
176: break;
177: }
178: }
179: };
180:
181: dbpListGridLayout = new GridLayout (1, 9);
182: dbpListPanel = ComponentFactory.addComponents (
183: new JPanel (dbpListGridLayout),
184: Multilingual.mlnText (ComponentFactory.createLabel ("Enabled"), "ja", "有効"),
185: Multilingual.mlnText (ComponentFactory.createLabel ("Address"), "ja", "アドレス"),
186: Multilingual.mlnText (ComponentFactory.createLabel ("Size"), "ja", "サイズ"),
187: Multilingual.mlnText (ComponentFactory.createLabel ("Mask"), "ja", "マスク"),
188: Multilingual.mlnText (ComponentFactory.createLabel ("Lower"), "ja", "下限"),
189: Multilingual.mlnText (ComponentFactory.createLabel ("Upper"), "ja", "上限"),
190: Multilingual.mlnText (ComponentFactory.createLabel ("Read"), "ja", "リード"),
191: Multilingual.mlnText (ComponentFactory.createLabel ("Write"), "ja", "ライト"),
192: Multilingual.mlnText (ComponentFactory.createLabel ("Count"), "ja", "回数"),
193: Multilingual.mlnText (ComponentFactory.createLabel ("Threshold"), "ja", "閾値"),
194: Multilingual.mlnText (ComponentFactory.createLabel ("Remove"), "ja", "削除")
195: );
196: dbpFrame = Multilingual.mlnTitle (
197: ComponentFactory.createRestorableSubFrame (
198: Settings.SGS_DBP_FRAME_KEY,
199: "Data break point",
200: null,
201: ComponentFactory.setPreferredSize (
202: ComponentFactory.createBorderPanel (
203:
204: ComponentFactory.createScrollPane (dbpListPanel),
205:
206: null,
207:
208: null,
209:
210: ComponentFactory.createFlowPanel (
211: FlowLayout.CENTER,
212: Multilingual.mlnText (ComponentFactory.createButton ("Add", listener), "ja", "追加")
213: )
214:
215: ),
216: 750, 100)
217: ),
218: "ja", "データブレークポイント");
219:
220: ComponentFactory.addListener (
221: dbpFrame,
222: new WindowAdapter () {
223: @Override public void windowClosing (WindowEvent we) {
224: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_DBP_VISIBLE_MASK;
225: }
226: });
227: }
228:
229:
230:
231:
232:
233:
234: public static void dbpBreak (int size, int address, int data, boolean written) {
235: if (size == DBP_BYTE) {
236: for (DataBreakRecord r : dbpList) {
237: if (r.dbrEnabled && (written ? r.dbrWrite : r.dbrRead)) {
238: if (r.dbrSize == DBP_BYTE) {
239: if (address == r.dbrAddress) {
240: int masked = data & r.dbrMask;
241: if (r.dbrLower <= r.dbrUpper ?
242: r.dbrLower <= masked && masked <= r.dbrUpper :
243: masked <= r.dbrUpper || r.dbrLower <= masked) {
244: r.dbrSetCount (r.dbrCount + 1);
245: if (r.dbrThreshold <= r.dbrCount) {
246: XEiJ.mpuStop (null);
247: }
248: }
249: }
250: }
251: }
252: }
253: } else if (size == DBP_WORD) {
254: for (DataBreakRecord r : dbpList) {
255: if (r.dbrEnabled && (written ? r.dbrWrite : r.dbrRead)) {
256: if (r.dbrSize == DBP_BYTE) {
257: if (address == r.dbrAddress) {
258: int masked = data >>> 8 & r.dbrMask;
259: if (r.dbrLower <= r.dbrUpper ?
260: r.dbrLower <= masked && masked <= r.dbrUpper :
261: masked <= r.dbrUpper || r.dbrLower <= masked) {
262: r.dbrSetCount (r.dbrCount + 1);
263: if (r.dbrThreshold <= r.dbrCount) {
264: XEiJ.mpuStop (null);
265: }
266: }
267: } else if (address + 1 == r.dbrAddress) {
268: int masked = data & r.dbrMask;
269: if (r.dbrLower <= r.dbrUpper ?
270: r.dbrLower <= masked && masked <= r.dbrUpper :
271: masked <= r.dbrUpper || r.dbrLower <= masked) {
272: r.dbrSetCount (r.dbrCount + 1);
273: if (r.dbrThreshold <= r.dbrCount) {
274: XEiJ.mpuStop (null);
275: }
276: }
277: }
278: } else if (r.dbrSize == DBP_WORD) {
279: if (address == r.dbrAddress) {
280: int masked = data & r.dbrMask;
281: if (r.dbrLower <= r.dbrUpper ?
282: r.dbrLower <= masked && masked <= r.dbrUpper :
283: masked <= r.dbrUpper || r.dbrLower <= masked) {
284: r.dbrSetCount (r.dbrCount + 1);
285: if (r.dbrThreshold <= r.dbrCount) {
286: XEiJ.mpuStop (null);
287: }
288: }
289: }
290: }
291: }
292: }
293: } else if (size == DBP_LONG) {
294: for (DataBreakRecord r : dbpList) {
295: if (r.dbrEnabled && (written ? r.dbrWrite : r.dbrRead)) {
296: if (r.dbrSize == DBP_BYTE) {
297: if (address == r.dbrAddress) {
298: int masked = data >>> 24 & r.dbrMask;
299: if (r.dbrLower <= r.dbrUpper ?
300: r.dbrLower <= masked && masked <= r.dbrUpper :
301: masked <= r.dbrUpper || r.dbrLower <= masked) {
302: r.dbrSetCount (r.dbrCount + 1);
303: if (r.dbrThreshold <= r.dbrCount) {
304: XEiJ.mpuStop (null);
305: }
306: }
307: } else if (address + 1 == r.dbrAddress) {
308: int masked = data >>> 16 & r.dbrMask;
309: if (r.dbrLower <= r.dbrUpper ?
310: r.dbrLower <= masked && masked <= r.dbrUpper :
311: masked <= r.dbrUpper || r.dbrLower <= masked) {
312: r.dbrSetCount (r.dbrCount + 1);
313: if (r.dbrThreshold <= r.dbrCount) {
314: XEiJ.mpuStop (null);
315: }
316: }
317: } else if (address + 2 == r.dbrAddress) {
318: int masked = data >>> 8 & r.dbrMask;
319: if (r.dbrLower <= r.dbrUpper ?
320: r.dbrLower <= masked && masked <= r.dbrUpper :
321: masked <= r.dbrUpper || r.dbrLower <= masked) {
322: r.dbrSetCount (r.dbrCount + 1);
323: if (r.dbrThreshold <= r.dbrCount) {
324: XEiJ.mpuStop (null);
325: }
326: }
327: } else if (address + 3 == r.dbrAddress) {
328: int masked = data & r.dbrMask;
329: if (r.dbrLower <= r.dbrUpper ?
330: r.dbrLower <= masked && masked <= r.dbrUpper :
331: masked <= r.dbrUpper || r.dbrLower <= masked) {
332: r.dbrSetCount (r.dbrCount + 1);
333: if (r.dbrThreshold <= r.dbrCount) {
334: XEiJ.mpuStop (null);
335: }
336: }
337: }
338: } else if (r.dbrSize == DBP_WORD) {
339: if (address == r.dbrAddress) {
340: int masked = data >> 16 & r.dbrMask;
341: if (r.dbrLower <= r.dbrUpper ?
342: r.dbrLower <= masked && masked <= r.dbrUpper :
343: masked <= r.dbrUpper || r.dbrLower <= masked) {
344: r.dbrSetCount (r.dbrCount + 1);
345: if (r.dbrThreshold <= r.dbrCount) {
346: XEiJ.mpuStop (null);
347: }
348: }
349: } else if (address + 2 == r.dbrAddress) {
350: int masked = data & r.dbrMask;
351: if (r.dbrLower <= r.dbrUpper ?
352: r.dbrLower <= masked && masked <= r.dbrUpper :
353: masked <= r.dbrUpper || r.dbrLower <= masked) {
354: r.dbrSetCount (r.dbrCount + 1);
355: if (r.dbrThreshold <= r.dbrCount) {
356: XEiJ.mpuStop (null);
357: }
358: }
359: }
360: } else if (r.dbrSize == DBP_LONG) {
361: if (address == r.dbrAddress) {
362: int masked = data & r.dbrMask;
363: if (Integer.compareUnsigned (r.dbrLower, r.dbrUpper) <= 0 ?
364: Integer.compareUnsigned (r.dbrLower, masked) <= 0 && Integer.compareUnsigned (masked, r.dbrUpper) <= 0 :
365: Integer.compareUnsigned (masked, r.dbrUpper) <= 0 || Integer.compareUnsigned (r.dbrLower, masked) <= 0) {
366: r.dbrSetCount (r.dbrCount + 1);
367: if (r.dbrThreshold <= r.dbrCount) {
368: XEiJ.mpuStop (null);
369: }
370: }
371: }
372: }
373: }
374: }
375: }
376: }
377:
378:
379:
380: public static class DataBreakRecord implements Comparable<DataBreakRecord> {
381:
382:
383: public int dbrAddress;
384: public int dbrSize;
385: public int dbrMask;
386: public int dbrLower;
387: public int dbrUpper;
388: public boolean dbrRead;
389: public boolean dbrWrite;
390:
391:
392: public boolean dbrEnabled;
393: public int dbrCount;
394: public int dbrThreshold;
395:
396:
397: public Box dbrEnabledBox;
398: public JCheckBox dbrEnabledCheckBox;
399: public Hex8Spinner dbrAddressSpinner;
400: public JSpinner dbrSizeSpinner;
401: public JLabel[] dbrSizeLabels;
402: public Hex8Spinner dbrMaskSpinner;
403: public Hex8Spinner dbrLowerSpinner;
404: public Hex8Spinner dbrUpperSpinner;
405: public JCheckBox dbrReadCheckBox;
406: public JCheckBox dbrWriteCheckBox;
407: public JSpinner dbrCountSpinner;
408: public SpinnerNumberModel dbrCountModel;
409: public JSpinner dbrThresholdSpinner;
410: public SpinnerNumberModel dbrThresholdModel;
411: public Box dbrRemoveBox;
412: public JButton dbrRemoveButton;
413:
414:
415: @Override public int compareTo (DataBreakRecord r) {
416: int t = Integer.compareUnsigned (dbrAddress, r.dbrAddress);
417: if (t == 0) {
418: t = Integer.compareUnsigned (dbrSize, r.dbrSize);
419: if (t == 0) {
420: t = Integer.compareUnsigned (dbrMask, r.dbrMask);
421: if (t == 0) {
422: t = Integer.compareUnsigned (dbrLower, r.dbrLower);
423: if (t == 0) {
424: t = Integer.compareUnsigned (dbrUpper, r.dbrUpper);
425: }
426: }
427: }
428: }
429: return t;
430: }
431:
432:
433:
434: @SuppressWarnings ("this-escape") public DataBreakRecord (int address, int size, int mask, int lower, int upper, boolean read, boolean write,
435: boolean enabled, int count, int threshold) {
436:
437:
438: mask &= size == DBP_BYTE ? 0xff : size == DBP_WORD ? 0xffff : 0xffffffff;
439: lower &= mask;
440: upper &= mask;
441:
442:
443: dbrAddress = address;
444: dbrSize = size;
445: dbrMask = mask;
446: dbrLower = lower;
447: dbrUpper = upper;
448: dbrRead = read;
449: dbrWrite = write;
450:
451:
452: dbrEnabled = enabled;
453: dbrCount = count;
454: dbrThreshold = threshold;
455:
456:
457: ActionListener listener = new ActionListener () {
458: @Override public void actionPerformed (ActionEvent ae) {
459: Object source = ae.getSource ();
460: switch (ae.getActionCommand ()) {
461: case "Enabled":
462: dbrSetEnabled (((JCheckBox) source).isSelected ());
463: break;
464: case "Read":
465: dbrRead = ((JCheckBox) source).isSelected ();
466: break;
467: case "Write":
468: dbrWrite = ((JCheckBox) source).isSelected ();
469: break;
470: case "Remove":
471: dbrRemove ();
472: break;
473: }
474: }
475: };
476:
477:
478: dbrEnabledBox = ComponentFactory.createGlueBox (
479: dbrEnabledCheckBox = Multilingual.mlnText (ComponentFactory.createCheckBox (dbrEnabled, "Enabled", listener), "ja", "有効")
480: );
481:
482:
483: dbrAddressSpinner = ComponentFactory.createHex8Spinner (dbrAddress, 0xffffffff, false, new ChangeListener () {
484: @Override public void stateChanged (ChangeEvent ce) {
485: if (dbpLock == 0) {
486: dbrSetAddress (((Hex8Spinner) ce.getSource ()).getIntValue ());
487: }
488: }
489: });
490:
491:
492: dbrSizeSpinner = Multilingual.mlnList (
493: ComponentFactory.createListSpinner (
494: DBP_SIZE_LIST_EN,
495: DBP_SIZE_LIST_EN.get (dbrSize),
496: new ChangeListener () {
497: @Override public void stateChanged (ChangeEvent ce) {
498: if (dbpLock == 0) {
499: SpinnerListModel model = (SpinnerListModel) ((JSpinner) ce.getSource ()).getModel ();
500: dbrSetSize (model.getList ().indexOf (model.getValue ()));
501: }
502: }
503: }),
504: "ja", DBP_SIZE_LIST_JA);
505:
506:
507: dbrMaskSpinner = ComponentFactory.createHex8Spinner (dbrMask, -1, false, new ChangeListener () {
508: @Override public void stateChanged (ChangeEvent ce) {
509: if (dbpLock == 0) {
510: dbrSetMask (((Hex8Spinner) ce.getSource ()).getIntValue ());
511: }
512: }
513: });
514:
515:
516: dbrLowerSpinner = ComponentFactory.createHex8Spinner (dbrLower, -1, false, new ChangeListener () {
517: @Override public void stateChanged (ChangeEvent ce) {
518: if (dbpLock == 0) {
519: dbrSetLower (((Hex8Spinner) ce.getSource ()).getIntValue ());
520: }
521: }
522: });
523:
524:
525: dbrUpperSpinner = ComponentFactory.createHex8Spinner (dbrUpper, -1, false, new ChangeListener () {
526: @Override public void stateChanged (ChangeEvent ce) {
527: if (dbpLock == 0) {
528: dbrSetUpper (((Hex8Spinner) ce.getSource ()).getIntValue ());
529: }
530: }
531: });
532:
533:
534: dbrReadCheckBox = Multilingual.mlnText (ComponentFactory.createCheckBox (dbrRead, "Read", listener), "ja", "リード");
535:
536:
537: dbrWriteCheckBox = Multilingual.mlnText (ComponentFactory.createCheckBox (dbrWrite, "Write", listener), "ja", "ライト");
538:
539:
540: dbrCountSpinner = ComponentFactory.createNumberSpinner (
541: dbrCountModel = new SpinnerNumberModel (dbrCount, 0, 99999999, 1),
542: 8,
543: new ChangeListener () {
544: @Override public void stateChanged (ChangeEvent ce) {
545: if (dbpLock == 0) {
546: dbrSetCount (dbrCountModel.getNumber ().intValue ());
547: }
548: }
549: });
550:
551:
552: dbrThresholdSpinner = ComponentFactory.createNumberSpinner (
553: dbrThresholdModel = new SpinnerNumberModel (dbrThreshold, 0, 99999999, 1),
554: 8,
555: new ChangeListener () {
556: @Override public void stateChanged (ChangeEvent ce) {
557: if (dbpLock == 0) {
558: dbrSetThreshold (dbrThresholdModel.getNumber ().intValue ());
559: }
560: }
561: });
562:
563:
564: dbrRemoveBox = ComponentFactory.createGlueBox (
565: dbrRemoveButton = Multilingual.mlnText (ComponentFactory.createButton ("Remove", listener), "ja", "削除")
566: );
567:
568:
569: dbpList.add (this);
570:
571:
572: dbpListGridLayout.setRows (dbpListGridLayout.getRows () + 1);
573: ComponentFactory.addComponents (
574: dbpListPanel,
575: dbrEnabledBox,
576: dbrAddressSpinner,
577: dbrSizeSpinner,
578: dbrMaskSpinner,
579: dbrLowerSpinner,
580: dbrUpperSpinner,
581: dbrReadCheckBox,
582: dbrWriteCheckBox,
583: dbrCountSpinner,
584: dbrThresholdSpinner,
585: dbrRemoveBox
586: );
587: dbpListPanel.validate ();
588: dbpListPanel.repaint ();
589:
590:
591: dbrSetEnabled (dbrEnabled);
592:
593: }
594:
595:
596:
597: public void dbrRemove () {
598:
599:
600: dbrSetEnabled (false);
601:
602:
603: ComponentFactory.removeComponents (
604: dbpListPanel,
605: dbrEnabledBox,
606: dbrAddressSpinner,
607: dbrSizeSpinner,
608: dbrMaskSpinner,
609: dbrLowerSpinner,
610: dbrUpperSpinner,
611: dbrCountSpinner,
612: dbrThresholdSpinner,
613: dbrRemoveBox
614: );
615: dbpListGridLayout.setRows (dbpListGridLayout.getRows () - 1);
616: dbpListPanel.validate ();
617: dbpListPanel.repaint ();
618:
619:
620: dbpList.remove (this);
621:
622: }
623:
624:
625:
626: public void dbrSetAddress (int address) {
627: if (dbrAddress != address) {
628: dbrAddress = address;
629: if (dbrAddressSpinner != null) {
630: dbpLock++;
631: dbrAddressSpinner.setIntValue (address);
632: dbpLock--;
633: }
634: }
635: }
636:
637:
638:
639: public void dbrSetSize (int size) {
640: if (dbrSize != size) {
641: dbrSize = size;
642: if (dbrSizeSpinner != null) {
643: dbpLock++;
644: dbrSizeSpinner.setValue (((SpinnerListModel) dbrSizeSpinner.getModel ()).getList ().get (size));
645: dbpLock--;
646: }
647: dbrSetMask (dbrMask & (dbrSize == DBP_BYTE ? 0xff : dbrSize == DBP_WORD ? 0xffff : 0xffffffff));
648: }
649: }
650:
651:
652:
653: public void dbrSetMask (int mask) {
654: mask &= dbrSize == DBP_BYTE ? 0xff : dbrSize == DBP_WORD ? 0xffff : 0xffffffff;
655: if (dbrMask != mask) {
656: dbrMask = mask;
657: if (dbrMaskSpinner != null) {
658: dbpLock++;
659: dbrMaskSpinner.setIntValue (mask);
660: dbpLock--;
661: }
662: dbrSetLower (dbrLower);
663: dbrSetUpper (dbrUpper);
664: }
665: }
666:
667:
668:
669: public void dbrSetLower (int lower) {
670: lower &= dbrMask;
671: if (dbrLower != lower) {
672: dbrLower = lower;
673: if (dbrLowerSpinner != null) {
674: dbpLock++;
675: dbrLowerSpinner.setIntValue (lower);
676: dbpLock--;
677: }
678: }
679: }
680:
681:
682:
683: public void dbrSetUpper (int upper) {
684: upper &= dbrMask;
685: if (dbrUpper != upper) {
686: dbrUpper = upper;
687: if (dbrUpperSpinner != null) {
688: dbpLock++;
689: dbrUpperSpinner.setIntValue (upper);
690: dbpLock--;
691: }
692: }
693: }
694:
695:
696:
697: public void dbrSetEnabled (boolean enabled) {
698: if (dbrEnabled != enabled) {
699: dbrEnabled = enabled;
700: dbrEnabledCheckBox.setSelected (enabled);
701: }
702: int p = dbrAddress >>> XEiJ.BUS_PAGE_BITS;
703: if (dbrEnabled) {
704:
705: dbpUserMap[p] = dbpSuperMap[p] = MemoryMappedDevice.MMD_DBP;
706: } else {
707:
708: boolean exists = false;
709: for (DataBreakRecord r : dbpList) {
710: if (r.dbrAddress >>> XEiJ.BUS_PAGE_BITS == p && r != this) {
711: exists = true;
712: break;
713: }
714: }
715: dbpUserMap[p] = exists ? MemoryMappedDevice.MMD_DBP : XEiJ.busUserMap[p];
716: dbpSuperMap[p] = exists ? MemoryMappedDevice.MMD_DBP : XEiJ.busSuperMap[p];
717: }
718: }
719:
720:
721:
722: public void dbrSetCount (int count) {
723: if (dbrCount != count) {
724: dbrCount = count;
725: if (dbrCountSpinner != null) {
726: dbpLock++;
727: dbrCountSpinner.setValue (Integer.valueOf (count));
728: dbpLock--;
729: }
730: }
731: }
732:
733:
734:
735: public void dbrSetThreshold (int threshold) {
736: if (dbrThreshold != threshold) {
737: dbrThreshold = threshold;
738: if (dbrThresholdSpinner != null) {
739: dbpLock++;
740: dbrThresholdSpinner.setValue (Integer.valueOf (threshold));
741: dbpLock--;
742: }
743: }
744: }
745:
746: }
747:
748:
749:
750: }
751:
752:
753: