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