1 /*
2 
3 Copyright 2021, dettus@dettus.net
4 
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7 
8 1. Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10 
11 2. Redistributions in binary form must reproduce the above copyright notice,
12    this list of conditions and the following disclaimer in the documentation
13    and/or other materials provided with the distribution.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 
27 */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "vm68k_datatypes.h"
32 #include "vm68k_decode.h"
33 
34 
35 // the purpose of this function is to perform a pattern matching to the instruction, and return the enumeration value.
36 // the more bits are constant, the higher should be the matche's priority.
vm68k_decode(tVM68k_uword opcode)37 tVM68k_instruction vm68k_decode(tVM68k_uword opcode)
38 {
39 
40 	// instructions with 16 constant bits
41 	if ((opcode&0xffff)==0x023c) return VM68K_INST_ANDItoCCR;	//ANDItoCCR: 0000 0010 0011 1100 00000000dddddddd
42 	if ((opcode&0xffff)==0x027c) return VM68K_INST_ANDItoSR;	//ANDItoSR:  0000 0010 0111 1100 dddddddddddddddd
43 	if ((opcode&0xffff)==0x0A3C) return VM68K_INST_EORItoCCR;	//EORItoCCR: 0000 1010 0011 1100 00000000dddddddd
44 	if ((opcode&0xffff)==0x0A7C) return VM68K_INST_EORItoSR;	//EORItoSR:  0000 1010 0111 1100 dddddddddddddddd
45 	if ((opcode&0xffff)==0x4AFC) return VM68K_INST_ILLEGAL;		//ILLEGAL:   0100 1010 1111 1100
46 	if ((opcode&0xffff)==0x4E71) return VM68K_INST_NOP;
47 	if ((opcode&0xffff)==0x003C) return VM68K_INST_ORItoCCR;	//ORItoCCR:  0000 0000 0011 1100 00000000dddddddd
48 	if ((opcode&0xffff)==0x007C) return VM68K_INST_ORItoSR;		//ORItoSR:   0000 0000 0111 1100 dddddddddddddddd
49 	if ((opcode&0xffff)==0x4E70) return VM68K_INST_RESET;		//RESET:     0100 1110 0111 0000
50 	if ((opcode&0xffff)==0x4E73) return VM68K_INST_RTE;		//RTE:       0100 1110 0111 0011
51 	if ((opcode&0xffff)==0x4E77) return VM68K_INST_RTR;		//RTR:       0100 1110 0111 0111
52 	if ((opcode&0xffff)==0x4E75) return VM68K_INST_RTS;		//RTS:       0100 1110 0111 0101
53 	if ((opcode&0xffff)==0x4E72) return VM68K_INST_STOP;		//STOP:      0100 1110 0111 0010 iiiiiiiiiiiiiiii
54 	if ((opcode&0xffff)==0x4E76) return VM68K_INST_TRAPV;		//TRAPV:     0100 1110 0111 0110
55 
56 
57 
58 	// instructions with 13 constant bits
59 	if ((opcode&0xfff8)==0x4E50) return VM68K_INST_LINK;		//LINK:      0100 1110 0101 0yyy dddddddddddddddd
60 	if ((opcode&0xfff8)==0x4840) return VM68K_INST_SWAP;		//SWAP:      0100 1000 0100 0yyy
61 	if ((opcode&0xfff8)==0x4E58) return VM68K_INST_UNLK;		//UNLK:      0100 1110 0101 1yyy
62 
63 	// instructions with 12 constant bits
64 	if ((opcode&0xfff0)==0x4E40) return VM68K_INST_TRAP;		//TRAP:      0100 1110 0100 vvvv
65 	if ((opcode&0xfff0)==0x4E60) return VM68K_INST_MOVEUSP;		//MOVE USP:  0100 1110 0110 dyyy
66 
67 	// instructions with 10 constant bits
68 	if ((opcode&0xffc0)==0x0800) return VM68K_INST_BTSTB;		//BTST.B:    0000 1000 00mm myyy 0000 0000 bbbb bbbb
69 	if ((opcode&0xffc0)==0x0840) return VM68K_INST_BCHGB;		//BCHG.B:    0000 1000 01mm myyy
70 	if ((opcode&0xffc0)==0x0880) return VM68K_INST_BCLRI;		//BCLRI:     0000 1000 10mm myyy
71 	if ((opcode&0xffc0)==0x08C0) return VM68K_INST_BSETB;		//BSET.B:    0000 1000 11mm myyy
72 
73 	if ((opcode&0xffc0)==0x44C0) return VM68K_INST_MOVEtoCCR;	//MOVEtoCCR: 0100 0100 11mm myyy
74 	if ((opcode&0xffc0)==0x40C0) return VM68K_INST_MOVEfromSR;	//MOVEfromSR:0100 0000 11mm myyy
75 	if ((opcode&0xffc0)==0x46C0) return VM68K_INST_MOVEtoSR;	//MOVEtoSR:  0100 0110 11mm myyy
76 	if ((opcode&0xffc0)==0x4840) return VM68K_INST_PEA;		//PEA:       0100 1000 01mm myyy
77 	if ((opcode&0xffc0)==0x4AC0) return VM68K_INST_TAS;		//TAS:       0100 1010 11mm myyy
78 	if ((opcode&0xffC0)==0x4EC0) return VM68K_INST_JMP;		//JMP:       0100 1110 11mm myyy
79 	if ((opcode&0xffC0)==0x4E80) return VM68K_INST_JSR;		//JSR:       0100 1110 10mm myyy
80 	if ((opcode&0xfe38)==0x4800) return VM68K_INST_EXT;		//EXT:       0100 100o oo00 0yyy
81 
82 	// instructions with 9 constant bits
83 	if ((opcode&0xf0f8)==0x50C8) return VM68K_INST_DBcc;		//DBcc:      0101 CCCC 1100 1yyy
84 	if ((opcode&0xf1f0)==0xC100) return VM68K_INST_ABCD;		//ABCD:      1100 xxx1 0000 myyy
85 	if ((opcode&0xf1f0)==0x8100) return VM68K_INST_SBCD;		//SBCD:      1000 xxx1 0000 ryyy
86 	if ((opcode&0xff80)==0x4880) return VM68K_INST_MOVEMregtomem;	//MOVEM:     0100 1000 1smm myyy	// reg to mem
87 	if ((opcode&0xff80)==0x4C80) return VM68K_INST_MOVEMmemtoreg;	//MOVEM:     0100 1100 1smm myyy	// mem to reg
88 	if ((opcode&0xf1C0)==0x01C0) return VM68K_INST_BSET;		//BSET:      0000 xxx1 11mm myyy
89 
90 	// instructions with 8 constant bits
91 	if ((opcode&0xff00)==0x4200) return VM68K_INST_CLR;		//CLR:       0100 0010 ssmm myyy
92 	if ((opcode&0xff00)==0x0C00) return VM68K_INST_CMPI;		//CMPI:      0000 1100 ssmm myyy
93 	if ((opcode&0xff00)==0x0A00) return VM68K_INST_EORI;		//EORI:      0000 1010 ssmm myyy
94 	if ((opcode&0xff00)==0x0600) return VM68K_INST_ADDI;		//ADDI:      0000 0110 ssmm myyy
95 	if ((opcode&0xff00)==0x0200) return VM68K_INST_ANDI;		//ANDI:      0000 0010 ssmm myyy
96 	if ((opcode&0xff00)==0x0000) return VM68K_INST_ORI;		//ORI:       0000 0000 ssmm myyy
97 	if ((opcode&0xff00)==0x4400) return VM68K_INST_NEG;		//NEG:       0100 0100 ssmm myyy
98 	if ((opcode&0xff00)==0x4000) return VM68K_INST_NEGX;		//NEGX:      0100 0000 ssmm myyy
99 	if ((opcode&0xff00)==0x4600) return VM68K_INST_NOT;		//NOT:       0100 0110 ssmm myyy
100 	if ((opcode&0xff00)==0x0400) return VM68K_INST_SUBI;		//SUBI:      0000 0100 ssmm myyy
101 	if ((opcode&0xff00)==0x4A00) return VM68K_INST_TST; 		//TST:       0100 1010 ssmm myyy
102 	if ((opcode&0xf0C0)==0xD0C0) return VM68K_INST_ADDA;		//ADDA:      1101 rrrs 11mm myyy	// IMPORTANT! THIS HAS TO COME BEFORE ADDX!
103 	if ((opcode&0xf130)==0xD100) return VM68K_INST_ADDX;		//ADDX:      1101 xxx1 ss00 myyy	// s=00,01,10=ADDX. 11=ADDA!!
104 	if ((opcode&0xf130)==0xC100) return VM68K_INST_EXG;		//EXG:       1100 xxx1 oo00 oyyy
105 	if ((opcode&0xf0C0)==0x90C0) return VM68K_INST_SUBA;		//SUBA:      1001 xxxo 11mm myyy	// probably the same problem as ADDA/ADDX.
106 	if ((opcode&0xf130)==0x9100) return VM68K_INST_SUBX;		//SUBX:      1001 yyy1 ss00 ryyy
107 	if ((opcode&0xf0C0)==0xB0C0) return VM68K_INST_CMPA;		//CMPA:      1011 xxxo 11mm myyy	/// IMPORANT! THIS HAS TO COME BEFORE CMPM!
108 	if ((opcode&0xf138)==0xb108) return VM68K_INST_CMPM;		//CMPM:      1011 xxx1 ss00 1yyy
109 
110 	// instructions with 7 constant bits
111 	if ((opcode&0xf1c0)==0x0140) return VM68K_INST_BCHG;		//BCHG:      0000 rrr1 01mm myyy
112 	if ((opcode&0xf1c0)==0x0180) return VM68K_INST_BCLR;		//BCLR:      0000 xxx1 10mm myyy
113 	if ((opcode&0xf1C0)==0x0100) return VM68K_INST_BTST;		//BTST:      0000 xxx1 00mm myyy
114 	if ((opcode&0xf1C0)==0x81C0) return VM68K_INST_DIVS;		//DIVS:      1000 xxx1 11mm myyy
115 	if ((opcode&0xf1C0)==0x80C0) return VM68K_INST_DIVU;		//DIVU:      1000 xxx0 11mm myyy
116 	if ((opcode&0xf1C0)==0xC1C0) return VM68K_INST_MULS;		//MULS:      1100 xxx1 11mm myyy
117 	if ((opcode&0xf1C0)==0xC0C0) return VM68K_INST_MULU;		//MULU:      1100 xxx0 11mm myyy
118 	if ((opcode&0xf1C0)==0x41C0) return VM68K_INST_LEA;		//LEA:       0100 xxx1 11mm myyy
119 	if ((opcode&0xf038)==0x0008) return VM68K_INST_MOVEP;		//MOVEP:     0000 xxxo oo00 1yyy dddddddddddddddd
120 
121 	// instructions with 6 constant bits
122 	if ((opcode&0xf018)==0xe018) return VM68K_INST_ROL_ROR;		//ROL/ROR:   1110 cccd ssl1 1yyy
123 	if ((opcode&0xf018)==0xe010) return VM68K_INST_ROXL_ROXR;	//ROXL/ROXR: 1110 cccd ssl1 0yyy
124 	if ((opcode&0xf0c0)==0x50C0) return VM68K_INST_SCC;		//SCC:       0101 CCCC 11mm myyy
125 	if ((opcode&0xf140)==0x4100) return VM68K_INST_CHK;		//CHK:       0100 xxx1 s0mm myyy
126 	if ((opcode&0xf018)==0xE008) return VM68K_INST_LSL_LSR; 	//LSL/LSR:   1110 cccd ssl0 1yyy
127 	if ((opcode&0xf018)==0xE000) return VM68K_INST_ASL_ASR; 	//ASL/ASR:   1110 cccd ssl0 0yyy
128 
129 	// instructions with 5 constant bits
130 	if ((opcode&0xf100)==0x5000) return VM68K_INST_ADDQ;		//ADDQ:      0101 ddd0 ssmm myyy
131 	if ((opcode&0xf100)==0xb100) return VM68K_INST_EOR;		//EOR:       1011 xxx1 oomm myyy
132 	if ((opcode&0xf100)==0x7000) return VM68K_INST_MOVEQ;		//MOVEQ:     0111 xxx0 dddd dddd
133 	if ((opcode&0xf000)==0x9000) return VM68K_INST_SUB;		//SUB:       1001 xxx0 oomm myyy
134 	if ((opcode&0xf100)==0x5100) return VM68K_INST_SUBQ;		//SUBQ:      0101 ddd1 ssmm myyy
135 	if ((opcode&0xC1C0)==0x0040) return VM68K_INST_MOVEA;		//MOVEA:     00ss xxx0 01mm myyy
136 
137 	// instructions with 4 constant bits
138 	//
139 	if ((opcode&0xf000)==0xD000) return VM68K_INST_ADD;		//ADD:	     1101 rrro oomm myyy
140 	if ((opcode&0xf000)==0xC000) return VM68K_INST_AND;		//AND:       1100 xxxo oomm myyy
141 	if ((opcode&0xf000)==0x6000) return VM68K_INST_BCC;		//BCC:       0110 CCCC dddd dddd
142 	if ((opcode&0xf000)==0xB000) return VM68K_INST_CMP;		//CMP:       1011 xxx0 oomm myyy
143 	if ((opcode&0xf000)==0x8000) return VM68K_INST_OR;		//OR:        1000 xxxo oomm myyy
144 
145 	// instructions with 2 constant bits
146 	if ((opcode&0xc000)==0x0000) return VM68K_INST_MOVE;		//MOVE:      00ss xxxm mmMM Myyy
147 
148 
149 
150 
151 	return VM68K_INST_UNKNOWN;
152 }
153 #ifdef	 DEBUG_PRINT
vm68k_get_instructionname(tVM68k_instruction instruction,char * name)154 void vm68k_get_instructionname(tVM68k_instruction instruction,char* name)
155 {
156 	#define	INSTFOUND(x)  case x: snprintf(name,64,#x); break;
157 	switch(instruction)
158 	{
159 		default:
160 			snprintf(name,64,"???");
161 			break;
162 		INSTFOUND(VM68K_INST_UNKNOWN)
163 		INSTFOUND(VM68K_INST_ABCD)
164 		INSTFOUND(VM68K_INST_ADD)
165 		INSTFOUND(VM68K_INST_ADDA)
166 		INSTFOUND(VM68K_INST_ADDI)
167 		INSTFOUND(VM68K_INST_ADDQ)
168 		INSTFOUND(VM68K_INST_ADDX)
169 		INSTFOUND(VM68K_INST_AND)
170 		INSTFOUND(VM68K_INST_ANDI)
171 		INSTFOUND(VM68K_INST_ANDItoCCR)
172 		INSTFOUND(VM68K_INST_ANDItoSR)
173 		INSTFOUND(VM68K_INST_ASL_ASR)
174 		INSTFOUND(VM68K_INST_BCC)
175 		INSTFOUND(VM68K_INST_BCHG)
176 		INSTFOUND(VM68K_INST_BCHGB)
177 		INSTFOUND(VM68K_INST_BCLR)
178 		INSTFOUND(VM68K_INST_BCLRI)
179 		INSTFOUND(VM68K_INST_BRA)
180 		INSTFOUND(VM68K_INST_BSET)
181 		INSTFOUND(VM68K_INST_BSETB)
182 		//INSTFOUND(VM68K_INST_BSR)
183 		INSTFOUND(VM68K_INST_BTST)
184 		INSTFOUND(VM68K_INST_BTSTB)
185 		INSTFOUND(VM68K_INST_CHK)
186 		INSTFOUND(VM68K_INST_CLR)
187 		INSTFOUND(VM68K_INST_CMP)
188 		INSTFOUND(VM68K_INST_CMPA)
189 		INSTFOUND(VM68K_INST_CMPI)
190 		INSTFOUND(VM68K_INST_CMPM)
191 		INSTFOUND(VM68K_INST_DBcc)
192 		INSTFOUND(VM68K_INST_DIVS)
193 		INSTFOUND(VM68K_INST_DIVU)
194 		INSTFOUND(VM68K_INST_EOR)
195 		INSTFOUND(VM68K_INST_EORI)
196 		INSTFOUND(VM68K_INST_EORItoCCR)
197 		INSTFOUND(VM68K_INST_EORItoSR)
198 		INSTFOUND(VM68K_INST_EXG)
199 		INSTFOUND(VM68K_INST_EXT)
200 		INSTFOUND(VM68K_INST_ILLEGAL)
201 		INSTFOUND(VM68K_INST_JMP)
202 		INSTFOUND(VM68K_INST_JSR)
203 		INSTFOUND(VM68K_INST_LEA)
204 		INSTFOUND(VM68K_INST_LINK)
205 		INSTFOUND(VM68K_INST_LSL_LSR)
206 		INSTFOUND(VM68K_INST_MOVE)
207 		INSTFOUND(VM68K_INST_MOVEA)
208 		INSTFOUND(VM68K_INST_MOVEtoCCR)
209 		INSTFOUND(VM68K_INST_MOVEfromSR)
210 		INSTFOUND(VM68K_INST_MOVEtoSR)
211 		INSTFOUND(VM68K_INST_MOVEUSP)
212 		INSTFOUND(VM68K_INST_MOVEMregtomem)
213 		INSTFOUND(VM68K_INST_MOVEMmemtoreg)
214 		INSTFOUND(VM68K_INST_MOVEP)
215 		INSTFOUND(VM68K_INST_MOVEQ)
216 		INSTFOUND(VM68K_INST_MULS)
217 		INSTFOUND(VM68K_INST_MULU)
218 		INSTFOUND(VM68K_INST_NBCD)
219 		INSTFOUND(VM68K_INST_NEG)
220 		INSTFOUND(VM68K_INST_NEGX)
221 		INSTFOUND(VM68K_INST_NOP)
222 		INSTFOUND(VM68K_INST_NOT)
223 		INSTFOUND(VM68K_INST_OR)
224 		INSTFOUND(VM68K_INST_ORI)
225 		INSTFOUND(VM68K_INST_ORItoCCR)
226 		INSTFOUND(VM68K_INST_ORItoSR)
227 		INSTFOUND(VM68K_INST_PEA)
228 		INSTFOUND(VM68K_INST_RESET)
229 		INSTFOUND(VM68K_INST_ROL_ROR)
230 		INSTFOUND(VM68K_INST_ROXL_ROXR)
231 		INSTFOUND(VM68K_INST_RTE)
232 		INSTFOUND(VM68K_INST_RTR)
233 		INSTFOUND(VM68K_INST_RTS)
234 		INSTFOUND(VM68K_INST_SBCD)
235 		INSTFOUND(VM68K_INST_SCC)
236 		INSTFOUND(VM68K_INST_STOP)
237 		INSTFOUND(VM68K_INST_SUB)
238 		INSTFOUND(VM68K_INST_SUBA)
239 		INSTFOUND(VM68K_INST_SUBI)
240 		INSTFOUND(VM68K_INST_SUBQ)
241 		INSTFOUND(VM68K_INST_SUBX)
242 		INSTFOUND(VM68K_INST_SWAP)
243 		INSTFOUND(VM68K_INST_TAS)
244 		INSTFOUND(VM68K_INST_TRAP)
245 		INSTFOUND(VM68K_INST_TRAPV)
246 		INSTFOUND(VM68K_INST_TST)
247 		INSTFOUND(VM68K_INST_UNLK)
248 	}
249 
250 }
251 #endif
252