annotate lwdisasm/insn.c @ 448:5cccf90bf838 3.0 tip

Fixed bug with complex external references generating invalid relocations in the object file
author lost@l-w.ca
date Fri, 05 Nov 2010 22:27:00 -0600
parents cba03436c720
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
409
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
1 /*
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
2 insn.c
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
3
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
4 Copyright © 2010 William Astle
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
5
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
6 This file is part of LWTOOLS.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
7
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
9 terms of the GNU General Public License as published by the Free Software
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
10 Foundation, either version 3 of the License, or (at your option) any later
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
11 version.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
12
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
13 This program is distributed in the hope that it will be useful, but WITHOUT
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
16 more details.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
17
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
18 You should have received a copy of the GNU General Public License along with
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
19 this program. If not, see <http://www.gnu.org/licenses/>.
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
20 */
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
21
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
22 #include <config.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
23
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
24 #include <stdio.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
25 #include <stdlib.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
26 #include <string.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
27
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
28 #include <lw_alloc.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
29 #include <lw_string.h>
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
30
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
31 #include "lwdisasm.h"
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
32
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
33 /*
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
34 this function creates a linedata_t with the disassembly of the
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
35 current location; returns NULL if the current disassembly point
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
36 is not a valid instruction or we are at the end of the input
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
37 */
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
38
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
39 #define fb(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return NULL; bytes[len++] = ____t; (d) = ____t; } while (0)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
40 #define fb2(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return "?"; bytes[(*len)++] = ____t; (d) = ____t; } while (0)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
41
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
42 char *encode_target(disasmstate_t *as, int addr, int section)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
43 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
44 symbol_t *s;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
45 static char buffer[256];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
46
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
47 s = find_symbol(as, addr, section);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
48 if (!s)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
49 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
50 sprintf(buffer, "$%04X", addr);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
51 return buffer;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
52 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
53 else
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
54 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
55 return s -> symbol;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
56 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
57 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
58
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
59 char *decode_indexed(disasmstate_t *as, char *bytes, int *len, int *target, int section)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
60 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
61 int pb, b1, b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
62 int rn;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
63 static char *rs[] = { "x", "y", "u", "s", "pcr" };
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
64 static char str[40];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
65 char *i1 = "", *i2 = "";
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
66 char *tstr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
67 *target = -1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
68
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
69 fb2(pb);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
70
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
71 rn = (pb >> 5) & 3;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
72
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
73 if (pb < 0x80)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
74 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
75 // 5 bit
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
76 b1 = pb & 15;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
77 if (pb & 16)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
78 b1 = b1 - 16;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
79
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
80 sprintf(str, "%d,%s", b1, rs[rn]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
81 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
82 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
83 if ((pb & 0x1F) == 0x1F)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
84 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
85 // extended indirect
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
86 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
87 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
88 sprintf(str, "[$%04X]", (b1 << 8) | b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
89 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
90 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
91
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
92 if (pb & 0x10)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
93 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
94 i1 = "[";
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
95 i2 = "]";
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
96 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
97
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
98 switch (pb & 0x0F)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
99 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
100 case 0: // ,r+
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
101 if (*i1 == '[')
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
102 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
103 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
104 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
105 sprintf(str, "%s,%s+%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
106 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
107
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
108 case 1: // ,r++
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
109 sprintf(str, "%s,%s++%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
110 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
111
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
112 case 2: // ,-r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
113 if (*i1 == '[')
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
114 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
115 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
116 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
117 sprintf(str, "%s,-%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
118 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
119
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
120 case 3: // ,--r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
121 sprintf(str, "%s,--%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
122 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
123
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
124 case 4: // ,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
125 sprintf(str, "%s,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
126 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
127
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
128 case 5: // B,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
129 sprintf(str, "%sb,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
130 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
131
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
132 case 6: // A,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
133 sprintf(str, "%sa,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
134 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
135
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
136 case 8: // 8 bit,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
137 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
138 if (b1 > 128)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
139 b1 -= 256;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
140 sprintf(str, "%s<$%02X,%s%s", i1, b1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
141 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
142
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
143 case 9: // 16 bit,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
144 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
145 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
146 b1 = (b1 << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
147 if (b2 > 32768)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
148 b2 -= 65536;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
149 sprintf(str, "%s>$%04X,%s%s", i1, b1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
150 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
151
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
152 case 11: // D,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
153 sprintf(str, "%sd,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
154 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
155
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
156 case 12: // 8 bit,PCR
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
157 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
158 if (b1 > 127)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
159 b1 -= 256;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
160 b1 += as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
161 b1 &= 0xFFFF;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
162 sprintf(str, "%s<%s,pcr%s", i1, encode_target(as, b1, section), i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
163 *target = b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
164 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
165
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
166 case 13: // 16 bit,PCR
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
167 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
168 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
169 b1 = (b1 << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
170 b1 += as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
171 b1 &= 0xFFFF;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
172 sprintf(str, "%s>%s,pcr%s", i1, encode_target(as, b1, section), i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
173 *target = b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
174 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
175 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
176
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
177 // if we got here, we have an illegal 6809
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
178 if (as -> target == TARGET_6809)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
179 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
180 sprintf(str, "?");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
181 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
182 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
183
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
184 // now sort out 6309 operations
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
185 pb &= 0x1F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
186
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
187 switch (pb)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
188 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
189 case 0x07:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
190 case 0x17:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
191 // E,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
192 sprintf(str, "%se,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
193 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
194
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
195 case 0x0A:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
196 case 0x1A:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
197 // F,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
198 sprintf(str, "%sf,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
199 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
200
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
201 case 0x0E:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
202 case 0x1E:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
203 // W,r
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
204 sprintf(str, "%sw,%s%s", i1, rs[rn], i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
205 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
206
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
207 case 0x0F:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
208 case 0x10:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
209 // W indexing
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
210 switch (rn)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
211 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
212 case 0: // ,W
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
213 sprintf(str, "%s,w%s", i1, i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
214 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
215
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
216 case 1: // 16 bit,W
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
217 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
218 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
219 b1 = (b1 << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
220 if (b1 > 32768)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
221 b1 -= 65536;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
222 sprintf(str, "%s>$%04X,w%s", i1, b1, i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
223 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
224
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
225 case 2: // ,W++
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
226 sprintf(str, "%s,w++%s", i1, i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
227 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
228
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
229 case 3: // ,--W
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
230 sprintf(str, "%s,--w%s", i1, i2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
231 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
232 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
233 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
234
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
235 sprintf(str, "?");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
236 return str;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
237 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
238
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
239 char *decode_operand(disasmstate_t *as, int addrmode, uint8_t *bytes, int *len, int *target, int section)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
240 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
241 int b1, b2, b3, b4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
242 static char insnbuffer[256];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
243 char *t;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
244 static char *rlist3[] = { "D", "X", "Y", "U", "S", "PC", "W", "V", "A", "B", "CC", "DP", "0", "0", "E", "F" };
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
245 static char *rlist8[] = { "D", "X", "Y", "U", "S", "PC", "?", "?", "A", "B", "CC", "DP", "?", "?", "?", "?" };
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
246 char **rlist = (as -> target == TARGET_6809) ? rlist8 : rlist3;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
247
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
248 switch (addrmode)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
249 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
250 case ADDR_IMM8:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
251 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
252 sprintf(insnbuffer, "#$%02X", b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
253 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
254
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
255 case ADDR_IMM16:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
256 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
257 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
258 sprintf(insnbuffer, "#$%04X", (b1 << 8) | b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
259 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
260
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
261 case ADDR_IMM32:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
262 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
263 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
264 fb2(b3);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
265 fb2(b4);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
266 sprintf(insnbuffer, "#$%08X", (b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
267 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
268
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
269 case ADDR_DIR:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
270 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
271 sprintf(insnbuffer, "<%s", encode_target(as, (as -> dpval << 8) | b1, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
272 *target = as -> dpval * 256 + b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
273 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
274
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
275 case ADDR_EXT:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
276 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
277 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
278 sprintf(insnbuffer, ">%s", encode_target(as, (b1 << 8) | b2, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
279 *target = (b1 << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
280 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
281
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
282 case ADDR_INH:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
283 *insnbuffer = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
284 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
285
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
286 case ADDR_IMM8DIR:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
287 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
288 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
289 sprintf(insnbuffer, "#$%02X;<%s", b1, encode_target(as, (as -> dpval << 8) | b2, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
290 *target = (as -> dpval << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
291 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
292
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
293 case ADDR_IMM8EXT:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
294 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
295 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
296 fb2(b3);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
297 sprintf(insnbuffer, "#$%02X;>%s", b1, encode_target(as, (b2 << 8) | b3, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
298 *target = (b2 << 8) | b3;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
299 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
300
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
301 case ADDR_IMM8IND:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
302 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
303 t = decode_indexed(as, bytes, len, target, section);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
304 sprintf(insnbuffer, "#$%02X;%s", b1, t);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
305 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
306
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
307 case ADDR_IND:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
308 t = decode_indexed(as, bytes, len, target, section);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
309 sprintf(insnbuffer, "%s", t);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
310 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
311
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
312 case ADDR_RTOR:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
313 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
314 b2 = b1 & 0x0F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
315 b1 = b1 >> 4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
316 sprintf(insnbuffer, "%s,%s", rlist[b1], rlist[b2]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
317 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
318
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
319 case ADDR_BITBIT:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
320 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
321 fb2(b2);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
322 sprintf(insnbuffer, "%s,%d,%d;<%s",
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
323 (b1 >> 6 == 0) ? "CC" : ((b1 >> 6 == 1) ? "A" : ((b1 >> 6 == 2) ? "B" : "?")),
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
324 (b1 >> 3) & 7, b1 & 7, encode_target(as, (as -> dpval << 8) | b2, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
325 *target = (as -> dpval << 8) | b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
326 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
327
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
328 case ADDR_PSHPULS:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
329 insnbuffer[0] = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
330 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
331 if (b1 & 0x01)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
332 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
333 strcat(insnbuffer, ",cc");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
334 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
335 if (b1 & 0x02)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
336 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
337 strcat(insnbuffer, ",a");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
338 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
339 if (b1 & 0x04)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
340 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
341 strcat(insnbuffer, ",b");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
342 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
343 if (b1 & 0x08)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
344 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
345 strcat(insnbuffer, ",dp");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
346 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
347 if (b1 & 0x10)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
348 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
349 strcat(insnbuffer, "x");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
350 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
351 if (b1 & 0x20)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
352 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
353 strcat(insnbuffer, "y");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
354 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
355 if (b1 & 0x40)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
356 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
357 strcat(insnbuffer, "u");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
358 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
359 if (b1 & 0x80)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
360 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
361 strcat(insnbuffer, "pc");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
362 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
363 return insnbuffer + 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
364 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
365
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
366 case ADDR_PSHPULU:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
367 insnbuffer[0] = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
368 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
369 if (b1 & 0x01)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
370 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
371 strcat(insnbuffer, ",cc");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
372 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
373 if (b1 & 0x02)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
374 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
375 strcat(insnbuffer, ",a");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
376 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
377 if (b1 & 0x04)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
378 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
379 strcat(insnbuffer, ",b");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
380 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
381 if (b1 & 0x08)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
382 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
383 strcat(insnbuffer, ",dp");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
384 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
385 if (b1 & 0x10)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
386 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
387 strcat(insnbuffer, "x");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
388 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
389 if (b1 & 0x20)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
390 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
391 strcat(insnbuffer, "y");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
392 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
393 if (b1 & 0x40)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
394 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
395 strcat(insnbuffer, "s");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
396 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
397 if (b1 & 0x80)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
398 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
399 strcat(insnbuffer, "pc");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
400 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
401 return insnbuffer + 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
402
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
403 case ADDR_REL8:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
404 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
405 if (b1 > 127)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
406 b1 -= 256;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
407 b1 += as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
408 b1 &= 0xFFFF;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
409 sprintf(insnbuffer, "%s", encode_target(as, b1, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
410 *target = b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
411 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
412
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
413 case ADDR_REL16:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
414 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
415 if (b1 > 32767)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
416 b1 -= 65536;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
417 b1 += as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
418 b1 &= 0xFFFF;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
419 sprintf(insnbuffer, "%s", encode_target(as, b1, section));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
420 *target = b2;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
421 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
422
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
423 case ADDR_TFMPP:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
424 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
425 b2 = b1 & 0x0F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
426 b1 >>= 4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
427 sprintf(insnbuffer, "%s+,%s+", rlist[b1], rlist[b2]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
428 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
429
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
430 case ADDR_TFMMM:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
431 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
432 b2 = b1 & 0x0F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
433 b1 >>= 4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
434 sprintf(insnbuffer, "%s-,%s-", rlist[b1], rlist[b2]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
435 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
436
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
437 case ADDR_TFMPC:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
438 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
439 b2 = b1 & 0x0F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
440 b1 >>= 4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
441 sprintf(insnbuffer, "%s+,%s", rlist[b1], rlist[b2]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
442 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
443
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
444 case ADDR_TFMCP:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
445 fb2(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
446 b2 = b1 & 0x0F;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
447 b1 >>= 4;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
448 sprintf(insnbuffer, "%s,%s+", rlist[b1], rlist[b2]);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
449 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
450
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
451 default:
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
452 sprintf(insnbuffer, "????");
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
453 break;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
454 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
455
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
456 return insnbuffer;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
457 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
458
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
459 linedata_t *disasm_insn(disasmstate_t *as)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
460 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
461 int curbyte;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
462 int b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
463 linedata_t *l;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
464 char *opcode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
465 int addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
466 char insnbuffer[256];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
467 char *t;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
468 int addr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
469 int len = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
470 int8_t bytes[10];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
471 int target = -1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
472
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
473 addr = as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
474
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
475 fb(curbyte);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
476 if (curbyte < 0)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
477 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
478
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
479 opcode = as->page0[curbyte].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
480 addrmode = as->page0[curbyte].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
481
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
482 if (addrmode == ADDR_PAGE1)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
483 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
484 fb(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
485 if (b1 < 0)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
486 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
487 opcode = as->page1[b1].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
488 addrmode = as->page1[b1].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
489 curbyte = (curbyte << 8) | b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
490 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
491 else if (addrmode == ADDR_PAGE2)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
492 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
493 fb(b1);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
494 if (b1 < 0)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
495 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
496 opcode = as->page2[b1].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
497 addrmode = as->page2[b1].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
498 curbyte = (curbyte << 8) | b1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
499 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
500
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
501 if (opcode == NULL)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
502 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
503
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
504 t = decode_operand(as, addrmode, bytes, &len, &target, 0);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
505
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
506 if (!t)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
507 return NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
508
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
509 // now create the line structure
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
510 l = lw_alloc(sizeof(linedata_t));
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
511 l -> next = NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
512 l -> prev = NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
513 l -> address = addr;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
514 l -> type = type_code;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
515 l -> length = len;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
516 l -> bytes = lw_alloc(len);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
517 memmove(l -> bytes, bytes, len);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
518 l -> isref = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
519 l -> symbol = NULL;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
520 l -> sectionref = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
521 sprintf(insnbuffer, "%s %s", opcode, t);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
522 l -> disasm = lw_strdup(insnbuffer);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
523 l -> target = target;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
524 return l;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
525 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
526
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
527 void redisasm_insn(disasmstate_t *as, linedata_t *l)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
528 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
529 char *opcode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
530 int addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
531 int len = 0;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
532 char bytes[15];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
533 int target = -1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
534 char *t;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
535 char insnbuf[256];
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
536 int ta;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
537 int ts;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
538
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
539 // short circuit if no target in this one
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
540 if (l -> target == -1)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
541 return;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
542
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
543 opcode = as -> page0[l -> bytes[0]].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
544 addrmode = as -> page0[l -> bytes[0]].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
545
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
546 ta = as -> curoff;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
547 as -> curoff = l -> address + 1;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
548
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
549 if (addrmode == ADDR_PAGE1)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
550 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
551 opcode = as -> page1[l -> bytes[1]].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
552 addrmode = as -> page1[l -> bytes[1]].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
553 as -> curoff++;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
554 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
555 else if (addrmode == ADDR_PAGE2)
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
556 {
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
557 opcode = as -> page2[l -> bytes[1]].op;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
558 addrmode = as -> page2[l -> bytes[1]].addrmode;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
559 as -> curoff++;
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
560 }
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
561
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
562 t = decode_operand(as, addrmode, bytes, &len, &target, l -> sectionref);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
563
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
564 // now create the line structure
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
565 lw_free(l -> disasm);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
566 sprintf(insnbuf, "%s %s", opcode, t);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
567 l -> disasm = lw_strdup(insnbuf);
cba03436c720 Checkpoint disassembler
lost@l-w.ca
parents:
diff changeset
568 }