DisassembleList.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: package xeij;
14:
15: import java.awt.*;
16: import java.awt.event.*;
17: import java.lang.*;
18: import java.util.*;
19: import javax.swing.*;
20: import javax.swing.event.*;
21:
22: public class DisassembleList {
23:
24: public static final int DDP_ITEM_SIZE = 0x00000002;
25: public static final int DDP_PAGE_SIZE = 0x00000400;
26: public static final int DDP_ITEM_MASK = -DDP_ITEM_SIZE;
27: public static final int DDP_PAGE_MASK = -DDP_PAGE_SIZE;
28: public static final int DDP_MAX_ITEMS = DDP_PAGE_SIZE / DDP_ITEM_SIZE + 2;
29:
30: public static final char[] DDP_MOVEQD0_BASE = (
31:
32:
33: "moveq.l #$xx,d0").toCharArray ();
34: public static final char[] DDP_DCW_BASE = (
35:
36:
37: ".dc.w $xxxx").toCharArray ();
38:
39: public static int ddpItemCount;
40: public static int ddpItemIndex;
41: public static int ddpItemAddress;
42: public static int ddpPageAddress;
43: public static final int[] ddpAddressArray = new int[DDP_MAX_ITEMS];
44: public static final int[] ddpSplitArray = new int[DDP_MAX_ITEMS];
45: public static final int[] ddpCaretArray = new int[DDP_MAX_ITEMS];
46: public static final boolean[] ddpDCWArray = new boolean[DDP_MAX_ITEMS];
47:
48: public static JFrame ddpFrame;
49: public static ScrollTextArea ddpBoard;
50: public static JTextArea ddpTextArea;
51:
52: public static Hex8Spinner ddpSpinner;
53:
54: public static int ddpPopupAddress;
55:
56: public static boolean ddpBacktraceOn;
57: public static long ddpBacktraceRecord;
58: public static SpinnerNumberModel ddpBacktraceModel;
59: public static JSpinner ddpBacktraceSpinner;
60: public static JCheckBox ddpBacktraceCheckBox;
61:
62: public static String ddpStoppedBy;
63: public static int ddpStoppedAddress;
64:
65: public static int ddpSupervisorMode;
66: public static JCheckBox ddpSupervisorCheckBox;
67:
68:
69:
70: public static void ddpInit () {
71:
72: ddpItemCount = 0;
73: ddpItemIndex = 0;
74: ddpItemAddress = -1;
75: ddpPageAddress = 0;
76: ddpSupervisorMode = 1;
77:
78:
79:
80:
81:
82: ddpFrame = null;
83:
84: }
85:
86:
87: public static void ddpStart () {
88: if (RestorableFrame.rfmGetOpened (Settings.SGS_DDP_FRAME_KEY)) {
89: ddpOpen (-1, -1, true);
90: }
91: }
92:
93:
94:
95:
96: public static void ddpOpen (int address, int supervisor, boolean forceUpdate) {
97: if (ddpFrame == null) {
98: ddpMake ();
99: }
100: ddpBacktraceRecord = -1L;
101: ddpUpdate (address, supervisor, forceUpdate);
102: XEiJ.pnlExitFullScreen (false);
103: ddpFrame.setVisible (true);
104: XEiJ.dbgVisibleMask |= XEiJ.DBG_DDP_VISIBLE_MASK;
105: }
106:
107:
108:
109: public static void ddpMake () {
110:
111:
112: ddpBoard = ComponentFactory.setPreferredSize (
113: ComponentFactory.setFont (new ScrollTextArea (), LnF.lnfMonospacedFont),
114: 500, 400);
115: ddpBoard.setMargin (new Insets (2, 4, 2, 4));
116: ddpBoard.setHighlightCursorOn (true);
117: ddpTextArea = ddpBoard.getTextArea ();
118: ddpTextArea.setEditable (false);
119:
120:
121: ddpSpinner = ComponentFactory.createHex8Spinner (ddpPageAddress, DDP_ITEM_MASK, true, new ChangeListener () {
122:
123:
124:
125:
126: @Override public void stateChanged (ChangeEvent ce) {
127: if (XEiJ.dbgEventMask == 0) {
128: ddpUpdate (ddpSpinner.getIntValue (), ddpSupervisorMode, false);
129: }
130: }
131: });
132:
133:
134:
135:
136:
137:
138: ComponentFactory.addListener (
139: ddpTextArea,
140: new CaretListener () {
141: @Override public void caretUpdate (CaretEvent ce) {
142: if (XEiJ.dbgEventMask == 0) {
143: int p = ce.getDot ();
144: if (p == ce.getMark ()) {
145: int i = Arrays.binarySearch (ddpSplitArray, 1, ddpItemCount, p + 1);
146: i = (i >> 31 ^ i) - 1;
147: ddpSpinner.setHintIndex (i);
148: }
149: }
150: }
151: });
152:
153:
154: ComponentFactory.addListener (
155: ddpTextArea,
156: new MouseAdapter () {
157: @Override public void mousePressed (MouseEvent me) {
158: if (XEiJ.mpuTask == null && me.isPopupTrigger ()) {
159: XEiJ.dbgShowPopup (me, ddpTextArea, true);
160: }
161: }
162: @Override public void mouseReleased (MouseEvent me) {
163: if (XEiJ.mpuTask == null && me.isPopupTrigger ()) {
164: XEiJ.dbgShowPopup (me, ddpTextArea, true);
165: }
166: }
167: });
168:
169:
170: ActionListener listener = new ActionListener () {
171: @Override public void actionPerformed (ActionEvent ae) {
172: Object source = ae.getSource ();
173: switch (ae.getActionCommand ()) {
174: case "Backtrace":
175: if (BranchLog.BLG_ON) {
176: ddpBacktraceOn = ((JCheckBox) ae.getSource ()).isSelected ();
177: if (XEiJ.dbgEventMask == 0) {
178: ddpUpdate (ddpAddressArray[ddpItemIndex], ddpSupervisorMode, true);
179: }
180: }
181: break;
182: case "User/Supervisor":
183: if (XEiJ.dbgEventMask == 0) {
184: ddpUpdate (ddpAddressArray[ddpItemIndex], ((JCheckBox) ae.getSource ()).isSelected () ? 1 : 0, true);
185: }
186: break;
187: }
188: }
189: };
190:
191:
192: if (BranchLog.BLG_ON) {
193: ddpBacktraceOn = false;
194: ddpBacktraceRecord = -1L;
195:
196:
197: ddpBacktraceModel = new ReverseLongModel (0L, 0L, 0L, 1L);
198: ddpBacktraceSpinner = ComponentFactory.createNumberSpinner (ddpBacktraceModel, 15, new ChangeListener () {
199: @Override public void stateChanged (ChangeEvent ce) {
200: if (XEiJ.dbgEventMask == 0 && XEiJ.mpuTask == null) {
201: long record = ddpBacktraceModel.getNumber ().longValue ();
202: int i = (char) record << BranchLog.BLG_RECORD_SHIFT;
203: if (
204: ddpBacktraceRecord < record) {
205: ddpBacktraceRecord = record;
206: ddpUpdate (BranchLog.blgArray[i] & ~1, BranchLog.blgArray[i] & 1, false);
207: } else if (record < ddpBacktraceRecord) {
208: ddpBacktraceRecord = record;
209: ddpUpdate (BranchLog.blgArray[i + 1], BranchLog.blgArray[i] & 1, false);
210: }
211: }
212: }
213: });
214:
215:
216: ddpBacktraceCheckBox =
217: Multilingual.mlnToolTipText (
218: ComponentFactory.createIconCheckBox (
219: ddpBacktraceOn,
220: XEiJ.createImage (
221: 20, 14,
222: "22222222222222222222" +
223: "2..................2" +
224: "2.......1..........2" +
225: "2......1.1.........2" +
226: "2.....1...1........2" +
227: "2....111.111.......2" +
228: "2......1.1.........2" +
229: "2......1.111111....2" +
230: "2......1......1....2" +
231: "2......111111.1....2" +
232: "2...........1.1....2" +
233: "2...........111....2" +
234: "2..................2" +
235: "22222222222222222222",
236: LnF.lnfRGB[0],
237: LnF.lnfRGB[6],
238: LnF.lnfRGB[12]),
239: XEiJ.createImage (
240: 20, 14,
241: "22222222222222222222" +
242: "2..................2" +
243: "2.......1..........2" +
244: "2......1.1.........2" +
245: "2.....1...1........2" +
246: "2....111.111.......2" +
247: "2......1.1.........2" +
248: "2......1.111111....2" +
249: "2......1......1....2" +
250: "2......111111.1....2" +
251: "2...........1.1....2" +
252: "2...........111....2" +
253: "2..................2" +
254: "22222222222222222222",
255: LnF.lnfRGB[0],
256: LnF.lnfRGB[12],
257: LnF.lnfRGB[12]),
258: "Backtrace", listener),
259: "ja", "バックトレース");
260: }
261:
262:
263: ddpSupervisorCheckBox =
264: Multilingual.mlnToolTipText (
265: ComponentFactory.createIconCheckBox (
266: ddpSupervisorMode != 0,
267: XEiJ.createImage (
268: 20, 14,
269: "22222222222222222222" +
270: "2..................2" +
271: "2..................2" +
272: "2.....11....11.....2" +
273: "2.....11....11.....2" +
274: "2.....11....11.....2" +
275: "2.....11....11.....2" +
276: "2.....11....11.....2" +
277: "2.....11....11.....2" +
278: "2.....11111111.....2" +
279: "2.....11111111.....2" +
280: "2..................2" +
281: "2..................2" +
282: "22222222222222222222",
283: LnF.lnfRGB[0],
284: LnF.lnfRGB[12],
285: LnF.lnfRGB[12]),
286: XEiJ.createImage (
287: 20, 14,
288: "22222222222222222222" +
289: "2..................2" +
290: "2..................2" +
291: "2.....11111111.....2" +
292: "2.....11111111.....2" +
293: "2.....11...........2" +
294: "2.....11111111.....2" +
295: "2.....11111111.....2" +
296: "2...........11.....2" +
297: "2.....11111111.....2" +
298: "2.....11111111.....2" +
299: "2..................2" +
300: "2..................2" +
301: "22222222222222222222",
302: LnF.lnfRGB[0],
303: LnF.lnfRGB[12],
304: LnF.lnfRGB[12]),
305: "User/Supervisor", listener),
306: "ja", "ユーザ/スーパーバイザ");
307:
308:
309: ddpFrame = Multilingual.mlnTitle (
310: ComponentFactory.createRestorableSubFrame (
311: Settings.SGS_DDP_FRAME_KEY,
312: "Disassemble list",
313: null,
314: ComponentFactory.createBorderPanel (
315: ddpBoard,
316: ComponentFactory.createHorizontalBox (
317: ddpSpinner,
318: ddpSupervisorCheckBox,
319: Box.createHorizontalStrut (12),
320: (BranchLog.BLG_ON ?
321: ComponentFactory.createHorizontalBox (
322: ddpBacktraceCheckBox,
323: ddpBacktraceSpinner,
324: Box.createHorizontalStrut (12)) :
325: null),
326: Box.createHorizontalGlue (),
327: XEiJ.mpuMakeOriIllegalCheckBox (),
328: XEiJ.mpuMakeStopOnErrorCheckBox (),
329: XEiJ.mpuMakeStopAtStartCheckBox (),
330: Box.createHorizontalStrut (12),
331: XEiJ.mpuMakeBreakButton (),
332: XEiJ.mpuMakeTraceButton (),
333: XEiJ.mpuMakeTrace10Button (),
334: XEiJ.mpuMakeTrace100Button (),
335: XEiJ.mpuMakeStepButton (),
336: XEiJ.mpuMakeStep10Button (),
337: XEiJ.mpuMakeStep100Button (),
338: XEiJ.mpuMakeReturnButton (),
339: XEiJ.mpuMakeRunButton ()
340: )
341: )
342: ),
343: "ja", "逆アセンブルリスト");
344: ComponentFactory.addListener (
345: ddpFrame,
346: new WindowAdapter () {
347: @Override public void windowClosing (WindowEvent we) {
348: XEiJ.dbgVisibleMask &= ~XEiJ.DBG_DDP_VISIBLE_MASK;
349: }
350: });
351:
352: ddpStoppedBy = null;
353: ddpStoppedAddress = -1;
354:
355: }
356:
357:
358:
359:
360: public static void ddpUpdate (int address, int supervisor, boolean forceUpdate) {
361:
362: XEiJ.dbgEventMask++;
363:
364: if (address == -1) {
365: ddpStoppedAddress = address = ddpStoppedBy == null ? XEiJ.regPC : XEiJ.regPC0;
366: forceUpdate = true;
367: } else if (address == 0) {
368: address = ddpItemAddress;
369: }
370:
371: if (supervisor == -1) {
372: supervisor = XEiJ.regSRS;
373: forceUpdate = true;
374: }
375:
376: if ((ddpSupervisorMode != 0) != (supervisor != 0)) {
377: ddpSupervisorMode = supervisor;
378: forceUpdate = true;
379: if (ddpSupervisorCheckBox.isSelected () != (supervisor != 0)) {
380: ddpSupervisorCheckBox.setSelected (supervisor != 0);
381: }
382: }
383:
384: if (forceUpdate) {
385: ddpItemCount = 0;
386: }
387:
388: address &= DDP_ITEM_MASK;
389:
390:
391: if (BranchLog.BLG_ON) {
392: if (XEiJ.mpuTask == null) {
393: long newestRecord = BranchLog.blgNewestRecord;
394: long oldestRecord = Math.max (0L, newestRecord - 65535);
395: if (
396: ddpBacktraceRecord < oldestRecord || newestRecord < ddpBacktraceRecord) {
397: ddpBacktraceRecord = newestRecord;
398: ddpBacktraceModel.setMaximum (Long.valueOf (newestRecord));
399: ddpBacktraceModel.setValue (Long.valueOf (newestRecord));
400: }
401: if (ddpBacktraceOn) {
402: int i = (char) ddpBacktraceRecord << BranchLog.BLG_RECORD_SHIFT;
403: if (address >>> 1 < BranchLog.blgArray[i] >>> 1) {
404: if (oldestRecord < ddpBacktraceRecord) {
405: ddpBacktraceRecord--;
406: ddpBacktraceModel.setValue (Long.valueOf (ddpBacktraceRecord));
407: address = BranchLog.blgArray[((char) ddpBacktraceRecord << BranchLog.BLG_RECORD_SHIFT) + 1] & ~1;
408: }
409: } else if (BranchLog.blgArray[i + 1] >>> 1 < address >>> 1) {
410: if (ddpBacktraceRecord < newestRecord) {
411: ddpBacktraceRecord++;
412: ddpBacktraceModel.setValue (Long.valueOf (ddpBacktraceRecord));
413: address = BranchLog.blgArray[(char) ddpBacktraceRecord << BranchLog.BLG_RECORD_SHIFT] & ~1;
414: }
415: }
416: }
417: }
418: }
419:
420: if (ddpItemCount != 0) {
421: int i = Arrays.binarySearch (ddpAddressArray, 1, ddpItemCount, address + 1);
422: i = (i >> 31 ^ i) - 1;
423: if (0 < i && i < ddpItemCount - 1 &&
424: ddpAddressArray[i] == address &&
425: !ddpDCWArray[i]) {
426:
427:
428:
429: ddpItemAddress = address;
430: if (ddpItemIndex != i) {
431: ddpItemIndex = i;
432: ddpTextArea.setCaretPosition (ddpCaretArray[i]);
433: }
434:
435:
436:
437:
438: XEiJ.dbgEventMask--;
439: return;
440: }
441: }
442:
443:
444: ddpItemAddress = address;
445:
446:
447:
448: ddpPageAddress = address & DDP_PAGE_MASK;
449: int pageEndAddress = ddpPageAddress + DDP_PAGE_SIZE;
450:
451:
452: ddpAddressArray[0] = ddpPageAddress - DDP_ITEM_SIZE;
453: ddpSplitArray[0] = 0;
454: ddpCaretArray[0] = 0;
455: StringBuilder sb = new StringBuilder (
456:
457:
458:
459:
460: " +0+1+2+3+4+5+6+7+8+9 ▲\n");
461: int itemCount = 1;
462: int itemAddress = ddpPageAddress;
463: int dcwAddress = pageEndAddress;
464: int dcwEndAddress = pageEndAddress;
465: boolean prevBranchFlag = false;
466:
467:
468:
469:
470: TreeMap<Integer,InstructionBreakPoint.InstructionBreakRecord> pointTable;
471: if (InstructionBreakPoint.IBP_ON) {
472: pointTable = InstructionBreakPoint.ibpPointTable;
473: }
474:
475: itemLoop:
476: do {
477: int itemEndAddress;
478: String code;
479:
480:
481:
482:
483:
484:
485:
486: if (dcwAddress <= itemAddress && itemAddress < dcwEndAddress) {
487: Disassembler.disStatus = 0;
488: int oc = MC68060.mmuPeekWordZeroCode (itemAddress, supervisor);
489: if ((oc & 0xfe00) == 0x7000 && MC68060.mmuPeekWordZeroCode (itemAddress + 2, supervisor) == 0x4e4f) {
490:
491: XEiJ.fmtHex2 (DDP_MOVEQD0_BASE, 10, oc);
492: code = String.valueOf (DDP_MOVEQD0_BASE);
493: } else {
494: XEiJ.fmtHex4 (DDP_DCW_BASE, 9, oc);
495: code = String.valueOf (DDP_DCW_BASE);
496: }
497: itemEndAddress = itemAddress + 2;
498: ddpDCWArray[itemCount] = true;
499: } else {
500: code = Disassembler.disDisassemble (new StringBuilder (), itemAddress, supervisor).toString ();
501: for (int t = itemAddress + 2; t < Disassembler.disPC; t += 2) {
502: if (t == address ||
503: InstructionBreakPoint.IBP_ON && pointTable.containsKey (t)) {
504:
505:
506:
507: dcwAddress = itemAddress;
508: dcwEndAddress = t;
509: continue itemLoop;
510: }
511: }
512: itemEndAddress = Disassembler.disPC;
513: ddpDCWArray[itemCount] = false;
514: }
515:
516:
517: if (prevBranchFlag) {
518: sb.append ('\n');
519: }
520:
521:
522: if (itemAddress == address) {
523: ddpItemIndex = itemCount;
524: }
525: ddpAddressArray[itemCount] = itemAddress;
526: ddpSplitArray[itemCount] = sb.length ();
527:
528: if (prevBranchFlag) {
529:
530: if (true) {
531: int i = sb.length ();
532: LabeledAddress.lblSearch (sb, itemAddress);
533: if (i < sb.length ()) {
534: sb.append ('\n');
535: }
536: }
537: }
538:
539:
540: if (itemAddress == ddpStoppedAddress && ddpStoppedBy != null) {
541: sb.append (ddpStoppedBy).append ('\n');
542: }
543:
544: ddpCaretArray[itemCount] = sb.length ();
545:
546:
547: int lineAddress = itemAddress;
548: int lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);
549:
550: XEiJ.fmtHex8 (sb, lineAddress).append (" ");
551:
552: for (int a = lineAddress; a < lineEndAddress; a += 2) {
553: XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
554: }
555: sb.append (XEiJ.DBG_SPACES, 0, 2 * Math.max (0, lineAddress + 10 - lineEndAddress) + 2);
556:
557: sb.append (code).append (XEiJ.DBG_SPACES, 0, Math.max (1, 68 - 32 - code.length ()));
558:
559: InstructionBreakPoint.InstructionBreakRecord r = InstructionBreakPoint.IBP_ON ? pointTable.get (itemAddress) : null;
560: if (r != null) {
561: if (r.ibrWaitInstruction != null) {
562: sb.append ("----");
563: }
564: if (r.ibrThreshold < 0) {
565: sb.append ("******");
566: } else if (r.ibrThreshold != 0x7fffffff) {
567: sb.append (r.ibrValue).append ('/').append (r.ibrThreshold);
568: }
569: } else {
570: for (int a = lineAddress; a < lineEndAddress; a++) {
571: int h = MC68060.mmuPeekByteZeroCode (a, supervisor);
572: int c;
573: if (0x81 <= h && h <= 0x9f || 0xe0 <= h && h <= 0xef) {
574: int l = MC68060.mmuPeekByteZeroCode (a + 1, supervisor);
575: if (0x40 <= l && l != 0x7f && l <= 0xfc) {
576: c = CharacterCode.chrSJISToChar[h << 8 | l];
577: if (c == 0) {
578: c = '※';
579: }
580: a++;
581: } else {
582: c = '.';
583: }
584: } else {
585: c = CharacterCode.chrSJISToChar[h];
586: if (c < 0x20 || c == 0x7f) {
587: c = '.';
588: }
589: }
590: sb.append ((char) c);
591: }
592: }
593: sb.append ('\n');
594:
595:
596: while (lineEndAddress < itemEndAddress) {
597: lineAddress = lineEndAddress;
598: lineEndAddress = Math.min (lineAddress + 10, itemEndAddress);
599:
600: XEiJ.fmtHex8 (sb, lineAddress).append (" ");
601:
602: for (int a = lineAddress; a < lineEndAddress; a += 2) {
603: XEiJ.fmtHex4 (sb, MC68060.mmuPeekWordZeroCode (a, supervisor));
604: }
605: sb.append (XEiJ.DBG_SPACES, 0, 2 * Math.max (0, lineAddress + 10 - lineEndAddress) + (2 + 68 - 32));
606:
607: for (int a = lineAddress; a < lineEndAddress; a++) {
608: int h = MC68060.mmuPeekByteZeroCode (a, supervisor);
609: int c;
610: if (0x81 <= h && h <= 0x9f || 0xe0 <= h && h <= 0xef) {
611: int l = MC68060.mmuPeekByteZeroCode (a + 1, supervisor);
612: if (0x40 <= l && l != 0x7f && l <= 0xfc) {
613: c = CharacterCode.chrSJISToChar[h << 8 | l];
614: if (c == 0) {
615: c = '※';
616: }
617: a++;
618: } else {
619: c = '.';
620: }
621: } else {
622: c = CharacterCode.chrSJISToChar[h];
623: if (c < 0x20 || c == 0x7f) {
624: c = '.';
625: }
626: }
627: sb.append ((char) c);
628: }
629: sb.append ('\n');
630: }
631:
632:
633: itemCount++;
634: itemAddress = itemEndAddress;
635:
636:
637: prevBranchFlag = (Disassembler.disStatus & Disassembler.DIS_ALWAYS_BRANCH) != 0;
638:
639: } while (itemAddress < pageEndAddress);
640:
641:
642: ddpAddressArray[itemCount] = itemAddress;
643: ddpSplitArray[itemCount] = sb.length ();
644: ddpCaretArray[itemCount] = sb.length ();
645: sb.append (
646:
647:
648: " +0+1+2+3+4+5+6+7+8+9 ▼");
649: itemCount++;
650: ddpItemCount = itemCount;
651:
652:
653: ddpTextArea.setText (sb.toString ());
654: ddpTextArea.setCaretPosition (ddpCaretArray[ddpItemIndex]);
655:
656:
657:
658:
659:
660: ddpSpinner.setHintArray (ddpAddressArray, itemCount);
661: ddpSpinner.setHintIndex (ddpItemIndex);
662:
663: XEiJ.dbgEventMask--;
664:
665: }
666:
667: }
668:
669:
670: