1 /*****************************************************************************
2 *
3 * 9900dasm.c
4 * TMS 9900 disassembler
5 *
6 * Copyright (c) 1998 John Butler, all rights reserved.
7 * Based on 6502dasm.c 6502/65c02/6510 disassembler by Juergen Buchmueller
8 *
9 * - This source code is released as freeware for non-commercial purposes.
10 * - You are free to use and redistribute this code in modified or
11 * unmodified form, provided you list me in the credits.
12 * - If you modify this source code, you must add a notice to each modified
13 * source file that it has been changed. If you're a nice person, you
14 * will clearly mark each change too. :)
15 * - The author of this copywritten work reserves the right to change the
16 * terms of its usage and license at any time, including retroactively
17 * - This entire notice must remain in the source code.
18 *
19 *****************************************************************************/
20
21
22 #include <stdio.h>
23 #include <string.h>
24 #include "memory.h"
25
26 #define RDOP(A) (cpu_readop(A) << 8) + (cpu_readop((A+1) & 0xffff))
27 #define RDWORD(A) (cpu_readop_arg(A) << 8) + (cpu_readop_arg((A+1) & 0xffff))
28
29 #define BITS_0to3 ((OP>>12) & 0xf)
30 #define BITS_2to5 ((OP>>10) & 0xf)
31 #define BITS_5to9 ((OP>>6) & 0x1f)
32 #define BITS_3to7 ((OP>>8) & 0x1f)
33 #define BITS_6to10 ((OP>>5) & 0x1f)
34
35 #define BITS_0to1 ((OP>>14) & 0x3)
36 #define BITS_0to4 ((OP>>11) & 0x1f)
37 #define BITS_0to2 ((OP>>13) & 0x7)
38 #define BITS_0to5 ((OP>>10) & 0x3f)
39
40 #define MASK 0x0000ffff
41 #define OPBITS(n1,n2) ((OP>>(15-(n2))) & (MASK>>(15-((n2)-(n1)))))
42
43
44 enum opcodes {
45 _a=0, _ab, _c, _cb, _s, _sb, _soc, _socb, _szc, _szcb,
46 _mov, _movb, _coc, _czc, _xor, _mpy, _div, _xop, _b, _bl,
47 _blwp, _clr, _seto, _inv, _neg, _abs, _swpb, _inc, _inct, _dec,
48 _dect, _x, _ldcr, _stcr, _sbo, _sbz, _tb, _jeq, _jgt, _jh,
49 _jhe, _jl, _jle, _jlt, _jmp, _jnc, _jne, _jno, _joc, _jop,
50 _sla, _sra, _src, _srl, _ai, _andi, _ci, _li, _ori, _lwpi,
51 _limi, _stst, _stwp, _rtwp, _idle, _rset, _ckof, _ckon, _lrex, _ill
52 };
53
54
55 static const char *token[]=
56 {
57 "a", "ab", "c", "cb", "s", "sb", "soc", "socb", "szc", "szcb",
58 "mov", "movb", "coc", "czc", "xor", "mpy", "div", "xop", "b", "bl",
59 "blwp", "clr", "seto", "inv", "neg", "abs", "swpb", "inc", "inct", "dec",
60 "dect", "x", "ldcr", "stcr", "sbo", "sbz", "tb", "jeq", "jgt", "jh",
61 "jhe", "jl", "jle", "jlt", "jmp", "jnc", "jne", "jno", "joc", "jop",
62 "sla", "sra", "src", "srl", "ai", "andi", "ci", "li", "ori", "lwpi",
63 "limi", "stst", "stwp", "rtwp", "idle", "rset", "ckof", "ckon", "lrex", "ill"
64 };
65
66
67 static const enum opcodes ops0to3[16]=
68 {
69 _ill, _ill, _ill, _ill, _szc, _szcb, _s, _sb, /*0000-0111*/
70 _c, _cb, _a, _ab, _mov, _movb, _soc, _socb /*1000-1111*/
71 };
72
73
74 static const enum opcodes ops2to5[16]=
75 {
76 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*0000-0111*/
77 _coc, _czc, _xor, _xop, _ldcr, _stcr, _mpy, _div /*1000-1111*/
78 };
79
80
81 static const enum opcodes ops5to9[32]=
82 {
83 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*00000-00111*/
84 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*01000-01111*/
85 _blwp, _b, _x, _clr, _neg, _inv, _inc, _inct, /*10000-10111*/
86 _dec, _dect, _bl, _swpb, _seto, _abs, _ill, _ill /*11000-11111*/
87 };
88
89
90 static const enum opcodes ops3to7[32]=
91 {
92 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*00000-00111*/
93 _sra, _srl, _sla, _src, _ill, _ill, _ill, _ill, /*01000-01111*/
94 _jmp, _jlt, _jle, _jeq, _jhe, _jgt, _jne, _jnc, /*10000-10111*/
95 _joc, _jno, _jl, _jh, _jop, _sbo, _sbz, _tb /*11000-11111*/
96 };
97
98
99 static const enum opcodes ops6to10[32]=
100 {
101 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*00000-00111*/
102 _ill, _ill, _ill, _ill, _ill, _ill, _ill, _ill, /*01000-01111*/
103 _li, _ai, _andi, _ori, _ci, _stwp, _stst, _lwpi, /*10000-10111*/
104 _limi, _ill, _idle, _rset, _rtwp, _ckon, _ckof, _lrex /*11000-11111*/
105 };
106
107 static int PC;
108
109
print_arg(int mode,int arg)110 static char *print_arg (int mode, int arg)
111 {
112 static char temp[20];
113 int base;
114
115 switch (mode)
116 {
117 case 0x0: /* workspace register */
118 sprintf (temp, "R%d", arg);
119 break;
120 case 0x1: /* workspace register indirect */
121 sprintf (temp, "*R%d", arg);
122 break;
123 case 0x2: /* symbolic|indexed */
124 base = RDWORD(PC); PC+=2;
125 if (arg) /* indexed */
126 sprintf (temp, "@>%04x(R%d)", base, arg);
127 else /* symbolic (direct) */
128 sprintf (temp, "@>%04x", base);
129 break;
130 case 0x3: /* workspace register indirect auto increment */
131 sprintf (temp, "*R%d+", arg);
132 break;
133 }
134 return temp;
135 }
136
137
138 /*****************************************************************************
139 * Disassemble a single command and return the number of bytes it uses.
140 *****************************************************************************/
Dasm9900(char * buffer,int pc)141 int Dasm9900 (char *buffer, int pc)
142 {
143 int OP, opc;
144 int sarg, darg, smode, dmode;
145
146 PC = pc;
147 OP = RDOP(PC); PC+=2;
148
149 if ((opc = ops0to3[BITS_0to3]) != _ill)
150 {
151 smode = OPBITS(10,11);
152 sarg = OPBITS(12,15);
153 dmode = OPBITS(4,5);
154 darg = OPBITS(6,9);
155
156 sprintf (buffer, "%-4s ", token[opc]);
157 strcat (buffer, print_arg (smode, sarg));
158 strcat (buffer, ",");
159 strcat (buffer, print_arg (dmode, darg));
160 }
161 else if (BITS_0to1==0 && (opc = ops2to5[BITS_2to5]) != _ill)
162 {
163 smode = OPBITS(10,11);
164 sarg = OPBITS(12,15);
165 darg = OPBITS(6,9);
166
167 if (darg==0 && (opc==_ldcr || opc==_stcr))
168 darg = 16;
169
170 if (opc==_xop || opc==_ldcr || opc==_stcr)
171 sprintf (buffer, "%-4s %s,%d", token[opc], print_arg (smode, sarg), darg);
172 else /* _coc, _czc, _xor, _mpy, _div */
173 sprintf (buffer, "%-4s %s,R%d", token[opc], print_arg (smode, sarg), darg);
174 }
175 else if (BITS_0to2==0 && (opc = ops3to7[BITS_3to7]) != _ill)
176 {
177 switch (opc)
178 {
179 case _sra: case _srl: case _sla: case _src:
180 sarg = OPBITS(12,15);
181 darg = OPBITS(8,11);
182
183 sprintf (buffer, "%-4s R%d,%d", token[opc], sarg, darg);
184 break;
185 case _jmp: case _jlt: case _jle: case _jeq: case _jhe: case _jgt:
186 case _jne: case _jnc: case _joc: case _jno: case _jl: case _jh: case _jop:
187 {
188 signed char displacement;
189
190 displacement = (signed char)OPBITS(8,15);
191 sprintf (buffer, "%-4s >%04x", token[opc], 0xffff & (PC + displacement * 2));
192 }
193 break;
194 case _sbo: case _sbz: case _tb:
195 {
196 signed char displacement;
197
198 displacement = (signed char)OPBITS(8,15);
199 sprintf (buffer, "%-4s >%04x", token[opc], 0xffff & displacement);
200 }
201 break;
202 }
203 }
204 else if (BITS_0to4==0 && (opc = ops5to9[BITS_5to9]) != _ill)
205 {
206 smode = OPBITS(10,11);
207 sarg = OPBITS(12,15);
208
209 sprintf (buffer, "%-4s %s", token[opc], print_arg (smode, sarg));
210 }
211 else if (BITS_0to5==0 && (opc = ops6to10[BITS_6to10]) != _ill)
212 {
213 switch (opc)
214 {
215 case _li: case _ai: case _andi: case _ori: case _ci:
216 darg = OPBITS(12,15);
217 sarg = RDWORD(PC); PC+=2;
218
219 sprintf (buffer, "%-4s R%d,>%04x", token[opc], darg, sarg);
220 break;
221 case _lwpi: case _limi:
222 sarg = RDWORD(PC); PC+=2;
223
224 sprintf (buffer, "%-4s >%04x", token[opc], sarg);
225 break;
226 case _stwp: case _stst:
227 sarg = OPBITS(12,15);
228
229 sprintf (buffer, "%-4s R%d", token[opc], sarg);
230 break;
231 case _idle: case _rset: case _rtwp: case _ckon: case _ckof: case _lrex:
232 sprintf (buffer, "%-4s", token[opc]);
233 break;
234 }
235 }
236 else
237 sprintf (buffer, "data >%04x", OP);
238
239 return PC - pc;
240 }
241