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