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 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "vm68k_datatypes.h"
33 #include "vm68k_decode.h"
34 #include "vm68k_loadstore.h"
35 #include "vm68k_macros.h"
36 #include "vm68k.h"
37 
38 #define	MAGICVALUE		0x564A3638	// "VM68"
39 
vm68k_checkcondition(tVM68k * pVM68k,tVM68k_ubyte condition)40 tVM68k_bool vm68k_checkcondition(tVM68k* pVM68k,tVM68k_ubyte condition)
41 {
42 	#define	CFLAG(pVM68k)	((((pVM68k)->sr)>>0)&1)
43 	#define	VFLAG(pVM68k)	((((pVM68k)->sr)>>1)&1)
44 	#define	ZFLAG(pVM68k)	((((pVM68k)->sr)>>2)&1)
45 	#define	NFLAG(pVM68k)	((((pVM68k)->sr)>>3)&1)
46 	#define	XFLAG(pVM68k)	((((pVM68k)->sr)>>4)&1)
47 
48         tVM68k_bool     condtrue;
49         switch(condition)
50         {
51                 case  0: condtrue=1;break;
52                 case  1: condtrue=0;break;
53                 case  2: //BHI high 0010 /C | /Z
54                          condtrue=!(CFLAG(pVM68k)|ZFLAG(pVM68k));
55                          break;
56                 case  3: //LS low or same 0011 C & Z
57                          condtrue= (CFLAG(pVM68k)|ZFLAG(pVM68k));
58                          break;
59                 case  4://BCC carry clear 0100 /C
60                          condtrue=!(CFLAG(pVM68k));
61                          break;
62                 case  5://BCS carry set 0101 C
63                          condtrue= (CFLAG(pVM68k));
64                          break;
65                 case  6://BNE not equal 0110 /Z
66                          condtrue=!(ZFLAG(pVM68k));
67                          break;
68                 case  7://BEQ equal 0111 Z
69                          condtrue= (ZFLAG(pVM68k));
70                          break;
71                 case  8://BVC overflow clear 1000 /V
72                          condtrue=!(VFLAG(pVM68k));
73                          break;
74                 case  9://BVS overflow set 1001 V
75                          condtrue= (VFLAG(pVM68k));
76                          break;
77                 case 10://BPL plus 1010 /N
78                          condtrue=!(NFLAG(pVM68k));
79                          break;
80                 case 11://BMI minus 1011 N
81                          condtrue= (NFLAG(pVM68k));
82                          break;
83                 case 12://BGE greater or equal 1100 (N & V) | (/N & /V), N and V are both set or both clear
84                          condtrue=!((NFLAG(pVM68k)^VFLAG(pVM68k)));
85                          break;
86                 case 13://BLT less than  1101 (N & /V) | (/N & V), N and V are either set or clear
87                          condtrue= ((NFLAG(pVM68k)^VFLAG(pVM68k)));
88                          break;
89                 case 14://BGT greater than 1110 (N & V & /Z) | (/N & /V & /Z)
90                          condtrue=!ZFLAG(pVM68k)&!((NFLAG(pVM68k)^VFLAG(pVM68k)));
91                          break;
92                 case 15://BLE less or equal 1111
93                          condtrue=ZFLAG(pVM68k)|((NFLAG(pVM68k)^VFLAG(pVM68k)));
94                          break;
95                 default:
96                          condtrue=0;
97                          break;
98         }
99         return condtrue;
100 }
101 
102 
103 
104 
vm68k_getsize(int * size)105 int vm68k_getsize(int* size)
106 {
107 	if (size==NULL) return VM68K_NOK_INVALID_PTR;
108 
109 	*size=sizeof(tVM68k);
110 	return	VM68K_OK;
111 }
112 
vm68k_init(void * hVM68k,void * pSharedMem,int sharedmemsize,int version)113 int vm68k_init(void* hVM68k,void* pSharedMem,int sharedmemsize,int version)
114 {
115 	tVM68k* pVM68k=(tVM68k*)hVM68k;
116 	if (hVM68k==NULL) return VM68K_NOK_INVALID_PTR;
117 	if (pSharedMem==NULL) return VM68K_NOK_INVALID_PARAMETER;
118 
119 	memset(hVM68k,0,sizeof(tVM68k));
120 	pVM68k->magic=MAGICVALUE;
121 	pVM68k->pcr=0;
122 	pVM68k->pMem=pSharedMem;
123 	pVM68k->memsize=sharedmemsize;
124 	pVM68k->a[7]=pVM68k->memsize-4;		// The stack pointer goes to the end of the memory
125 
126 	pVM68k->version=version;
127 
128 	return	VM68K_OK;
129 
130 }
vm68k_singlestep(void * hVM68k,unsigned short opcode)131 int vm68k_singlestep(void *hVM68k,unsigned short opcode)
132 {
133 	tVM68k* pVM68k=(tVM68k*)hVM68k;
134 	tVM68k_instruction	instruction;
135 	tVM68k_ubyte		addrmode;
136 	tVM68k_ubyte		reg1,reg2;
137 	tVM68k_types		datatype;
138 	tVM68k_next		next;
139 
140 	tVM68k_slong		ea;
141 	tVM68k_ulong		operand1,operand2;
142 	tVM68k_uint64		result;
143 
144 	tVM68k_ubyte		condition;
145 	tVM68k_sword		displacement;
146 	tVM68k_bool		direction;
147 
148 	int retval;
149 	int i;
150 
151 	if (hVM68k==NULL) return VM68K_NOK_INVALID_PTR;
152 	if (pVM68k->magic!=MAGICVALUE) return VM68K_NOK_INVALID_PARAMETER;
153 
154 	retval=VM68K_NOK_UNKNOWN_INSTRUCTION;
155 
156 	instruction=vm68k_decode(opcode);
157 	// decode the opcode
158 	reg1=(opcode>>9)&0x7;
159 	addrmode=(opcode>>3)&0x7;
160 	reg2=(opcode>>0)&0x7;
161 	datatype=(tVM68k_types)(opcode>>6)&0x3;
162 
163 
164 	// branches
165 	condition=(opcode>>8)&0xf;
166 	displacement=(tVM68k_sword)((tVM68k_sbyte)(opcode&0xff));
167 
168 	// alu operations
169 	direction=(opcode>>8)&0x1;
170 
171 	INITNEXT(pVM68k,next);
172 	result=0;
173 	switch(instruction)
174 	{
175 		case VM68K_INST_TRAP:
176 			printf("\x1b[1;37;42mtrap #%d\n",opcode&0xf);
177 			for (i=0;i<16;i++)
178 			{
179 				printf(" ** trap %d stack %2d %08X \n",opcode&0xf,i,READ_INT32BE(pVM68k->pMem,pVM68k->a[7]-i*4));
180 			}
181 			printf("\x1b[0m\n");
182 			retval=VM68K_OK;
183 			break;
184 		case VM68K_INST_MULU:
185 			retval=vm68k_resolve_ea(pVM68k,&next,VM68K_WORD,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
186 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,VM68K_WORD,ea,&operand1);
187 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,VM68K_WORD,DATAREGADDR(reg1),&operand2);
188 			if (retval==VM68K_OK) result=((unsigned int)operand1&0xffff)*((unsigned short)operand2&0xffff);
189 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,VM68K_LONG,operand1,operand2,result);
190 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,VM68K_LONG,DATAREGADDR(reg1),result);
191 			break;
192 		case VM68K_INST_DIVU:
193 			// FIXME: division by 0?
194 			retval=vm68k_resolve_ea(pVM68k,&next,VM68K_WORD,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
195 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,VM68K_WORD,ea,&operand1);
196 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,VM68K_WORD,DATAREGADDR(reg1),&operand2);
197 			// upper 16 bits are the remainder
198 			if (retval==VM68K_OK) result=(((unsigned int)operand1&0xffff)%((unsigned short)operand2&0xffff))<<16;
199 			// lower 16 bits are the quotient
200 			if (retval==VM68K_OK) result|=(((unsigned int)operand1&0xffff)/((unsigned short)operand2&0xffff))&0xffff;
201 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,VM68K_LONG,operand1,operand2,result);
202 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,VM68K_LONG,DATAREGADDR(reg1),result);
203 			break;
204 		case VM68K_INST_ADD:
205 		case VM68K_INST_CMP:
206 		case VM68K_INST_SUB:
207 			if (instruction==VM68K_INST_CMP)
208 			{
209 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
210 			} else {
211 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,direction?VM68K_LEGAL_MEMORYALTERATE:VM68K_LEGAL_ALL,&ea);
212 			}
213 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea,&operand1);
214 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,DATAREGADDR(reg1),&operand2);
215 			if (instruction==VM68K_INST_SUB || instruction==VM68K_INST_CMP)
216 			{
217 				if (direction)
218 				{
219 					result=operand1-operand2;
220 				} else {
221 					result=operand2-operand1;
222 				}
223 			} else {
224 				result=operand2+operand1;
225 			}
226 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,datatype,operand1,operand2,result);
227 			if (retval==VM68K_OK && instruction!=VM68K_INST_CMP) retval=vm68k_storeresult(pVM68k,&next,datatype,(direction)?ea:DATAREGADDR(reg1),result);
228 		break;
229 		case VM68K_INST_ADDA:
230 		case VM68K_INST_CMPA:
231 		case VM68K_INST_SUBA:
232 			if (datatype==VM68K_UNKNOWN)
233 			{
234 				tVM68k_types datatype2;
235 				tVM68k_types datatype3;
236 				datatype2=((opcode>>8)&1)?VM68K_LONG:VM68K_WORD;
237 				if (pVM68k->version==4)
238 				{
239 					datatype3=VM68K_LONG;
240 				}
241 				else
242 				{
243 					datatype3=datatype2;
244 				}
245 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
246 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype2,ea,&operand2);
247 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype3,ADDRREGADDR(reg1),&operand1);
248 
249 				if (instruction==VM68K_INST_SUBA || instruction==VM68K_INST_CMPA)
250 				{
251 					result=operand1-operand2;
252 				} else {
253 					result=operand2+operand1;
254 				}
255 				if (retval==VM68K_OK && instruction==VM68K_INST_CMPA) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,datatype2,operand1,operand2,result);
256 				if (retval==VM68K_OK && instruction!=VM68K_INST_CMPA) retval=vm68k_storeresult(pVM68k,&next,datatype3,ADDRREGADDR(reg1),result);
257 			}
258 		break;
259 		case VM68K_INST_ADDI:
260 		case VM68K_INST_CMPI:
261 		case VM68K_INST_SUBI:
262 			READEXTENSION(pVM68k,&next,datatype,operand1);
263 			retval=VM68K_OK;
264 			switch(datatype)
265 			{
266 				case VM68K_BYTE:	operand1=(tVM68k_slong)((tVM68k_sbyte)(operand1&      0xff));break;
267 				case VM68K_WORD:	operand1=(tVM68k_slong)((tVM68k_sword)(operand1&    0xffff));break;
268 				case VM68K_LONG:	operand1=(tVM68k_slong)((tVM68k_slong)(operand1&0xffffffff));break;
269 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
270 			}
271 			if (retval==VM68K_OK) retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
272 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea,&operand2);
273 			if (instruction==VM68K_INST_SUBI || instruction==VM68K_INST_CMPI)
274 			{
275 				result=operand2-operand1;	// Checked 0c01
276 			} else {
277 				result=operand2+operand1;
278 			}
279 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,datatype,operand1,operand2,result);
280 			if (retval==VM68K_OK && instruction!=VM68K_INST_CMPI) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
281 		break;
282 		case VM68K_INST_ADDQ:
283 		case VM68K_INST_SUBQ:
284 		{
285 			tVM68k_sbyte quick;
286 			tVM68k_bool version3_workaround;
287 			retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_ALTERABLEADRESSING,&ea);
288 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea,&operand2);
289 			quick=reg1;
290 			operand1=quick;
291 			if (operand1==0) operand1=8;
292 			if (instruction==VM68K_INST_SUBQ)
293 			{
294 				result=operand2-operand1;
295 			} else {
296 				result=operand2+operand1;
297 			}
298 			version3_workaround=next.zflag;		// starting with version 3, the z-flag needed to be preserved. this was an inconsistency in the original engine, that just stuck.
299 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,datatype,operand1,operand2,result);
300 			if ((pVM68k->version>=3)  && (instruction==VM68K_INST_ADDQ)) next.zflag=version3_workaround;
301 			if (retval==VM68K_OK && instruction!=VM68K_INST_CMPI) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
302 		}
303 		break;
304 		case VM68K_INST_EXG:
305 		{
306 			tVM68k_sbyte	opmode;
307 			opmode=(opcode>>3)&0x1f;
308 			switch(opmode)
309 			{
310 				case 8:	next.d[reg1]=pVM68k->d[reg2];
311 					next.d[reg2]=pVM68k->d[reg1];break;	// 01000= data registers.
312 				case 9:	next.a[reg1]=pVM68k->a[reg2];
313 					next.a[reg2]=pVM68k->a[reg1];break;	// 01001= addr registers.
314 				case 17:next.d[reg1]=pVM68k->a[reg2];
315 					next.a[reg2]=pVM68k->d[reg1];break;	// 10001= data +addr registers.
316 			}
317 			retval=VM68K_OK;
318 		}
319 		break;
320 		case VM68K_INST_MOVEQ:
321 		{
322 			tVM68k_types	datatype2;
323 			tVM68k_sbyte data;
324 			datatype2=VM68K_LONG;
325 
326 			data=opcode&0xff;
327 			result=(tVM68k_slong)data;
328 			retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype2,0,0,result);
329 			next.cflag=next.vflag=0;
330 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,DATAREGADDR(reg1),result);
331 		}
332 		break;
333 
334 
335 		case VM68K_INST_AND:
336 		case VM68K_INST_EOR:
337 		case VM68K_INST_OR:
338 			// direction=1: <en>-Dn -> <ea>
339 			// direction=0: Dn-<ea> -> Dn
340 			if (instruction==VM68K_INST_EOR)	// TODO: is this really neessary?
341 			{
342 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
343 			}
344 			else
345 			{
346 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,direction?VM68K_LEGAL_MEMORYALTERATE:VM68K_LEGAL_ALL,&ea);
347 			}
348 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand2);
349 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,DATAREGADDR(reg1),&operand1);
350 			switch (instruction)
351 			{
352 				case VM68K_INST_AND:	result=operand1&operand2;break;
353 				case VM68K_INST_EOR:	result=operand1^operand2;break;
354 				case VM68K_INST_OR:	result=operand1|operand2;break;
355 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
356 			}
357 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype,operand1,operand2,result);
358 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype,(direction)?ea:DATAREGADDR(reg1),result);
359 		break;
360 		case VM68K_INST_ANDI:
361 		case VM68K_INST_EORI:
362 		case VM68K_INST_ORI:
363 			READEXTENSION(pVM68k,&next,datatype,operand1);
364 			retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
365 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand2);
366 			switch (instruction)
367 			{
368 				case VM68K_INST_ANDI:result=operand1&operand2;break;
369 				case VM68K_INST_EORI:result=operand1^operand2;break;
370 				case VM68K_INST_ORI: result=operand1|operand2;break;
371 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
372 			}
373 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype,operand1,operand2,result);
374 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
375 
376 		break;
377 		case VM68K_INST_BCC:
378 			if (displacement==0)
379 			{
380 				displacement=READEXTENSIONWORD(pVM68k,&next);
381 			}
382 			if (condition==1) 	// BSR
383 			{
384 				PUSHLONGTOSTACK(pVM68k,&next,(next.pcr));
385 			}
386 			if (vm68k_checkcondition(pVM68k,condition) || condition==1)
387 			{
388 				next.pcr=pVM68k->pcr+displacement;
389 			}
390 			retval=VM68K_OK;
391 		break;
392 		case VM68K_INST_MOVE:
393 		case VM68K_INST_MOVEA:
394 		{
395 			tVM68k_types	datatype2;
396 			tVM68k_ubyte	addrmode_dest;
397 			tVM68k_slong	ea_dest;
398 			datatype2=VM68K_UNKNOWN;
399 			retval=VM68K_OK;
400 			switch ((opcode>>12)&0x3)
401 			{
402 				case 1: datatype2=VM68K_BYTE;break;
403 				case 3: datatype2=VM68K_WORD;break;
404 				case 2: datatype2=VM68K_LONG;break;
405 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;
406 			}
407 			addrmode_dest=(opcode>>6)&0x7;
408 			if (retval==VM68K_OK) retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_ALL,&ea);
409 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
410 
411 
412 			// TODO: I had a problem here, when the addrmode was 7/4 and the size was BYTE. lets see what happens.
413 			if (retval==VM68K_OK) retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode_dest,reg1,(instruction==VM68K_INST_MOVE)?VM68K_LEGAL_DATAALTERATE:VM68K_LEGAL_ALL,&ea_dest);
414 			if (retval==VM68K_OK) result=operand2;
415 			if (retval==VM68K_OK && instruction!=VM68K_INST_MOVEA) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype2,0,operand2,result);
416 
417 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea_dest,result);
418 		}
419 		break;
420 		case VM68K_INST_NEG:
421 		case VM68K_INST_NEGX:
422 		case VM68K_INST_NOT:
423 		{
424 			retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
425 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea,&operand2);
426 			result=(instruction==VM68K_INST_NOT)?(~operand2):(0-operand2);
427 			result=result-((instruction==VM68K_INST_NEGX)&next.xflag);
428 			operand1=0;
429 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype,operand1,operand2,result);
430 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
431 
432 		}
433 		break;
434 
435 		case VM68K_INST_JMP:
436 		case VM68K_INST_JSR:
437 		{
438 			tVM68k_types	datatype2;
439 			datatype2=VM68K_LONG;
440 			retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_CONTROLADDRESSING,&ea);
441 			operand2=ea;
442 			if (instruction==VM68K_INST_JSR && retval==VM68K_OK)
443 			{
444 				PUSHLONGTOSTACK(pVM68k,&next,(next.pcr));
445 			}
446 			// TODO: why this way?
447 			switch (addrmode)
448 			{
449 				case VM68K_AM_INDIR:
450 					next.pcr=operand2%pVM68k->memsize;
451 					break;
452 				default:
453 					next.pcr=operand2;	// wonderland
454 					break;
455 			}
456 		}
457 		break;
458 		case VM68K_INST_RTS:
459 			retval=VM68K_OK;
460 			POPLONGFROMSTACK(pVM68k,&next,next.pcr);
461 		break;
462 		case VM68K_INST_ANDItoSR:
463 		case VM68K_INST_EORItoSR:
464 		case VM68K_INST_ORItoSR:
465 		case VM68K_INST_ANDItoCCR:
466 		case VM68K_INST_EORItoCCR:
467 		case VM68K_INST_ORItoCCR:
468 			retval=VM68K_OK;
469 			operand2=READEXTENSIONWORD(pVM68k,&next);
470 			operand1=0xffff;
471 			switch (instruction)
472 			{
473 				case VM68K_INST_ANDItoCCR:	operand1&=0x1f;
474 				case VM68K_INST_ANDItoSR:	operand2&=next.sr;break;
475 
476 				case VM68K_INST_EORItoCCR:	operand1&=0x1f;
477 				case VM68K_INST_EORItoSR:	operand2^=next.sr;break;
478 
479 				case VM68K_INST_ORItoCCR:	operand1&=0x1f;
480 				case VM68K_INST_ORItoSR:	operand2|=next.sr;break;
481 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
482 			}
483 			result=operand1&operand2;
484 
485 			next.override_sr=1;
486 			next.sr&=~operand1;
487 			next.sr|=operand2;
488 		break;
489 		case VM68K_INST_MOVEfromSR:
490 			{
491 				tVM68k_types	datatype2;
492 				datatype2=VM68K_WORD;
493 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
494 				result=next.sr&0xffff;
495 				if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
496 			}
497 			break;
498 
499 		case VM68K_INST_MOVEtoCCR:
500 		case VM68K_INST_MOVEtoSR:
501 			{
502 				tVM68k_types	datatype2;
503 				datatype2=VM68K_WORD;
504 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_DATAADDRESSING,&ea);
505 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
506 				if (retval==VM68K_OK)
507 				{
508 					next.override_sr=1;
509 					next.sr=(instruction==VM68K_INST_MOVEtoCCR)?((next.sr&0xffe0)|(operand2&0x1f)):operand2;
510 				}
511 			}
512 		break;
513 		case VM68K_INST_MOVEMregtomem:
514 			{
515 				tVM68k_types datatype2;
516 				tVM68k_uword bitmask=0;
517 				datatype2=((opcode>>6)&1)?VM68K_LONG:VM68K_WORD;
518 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_CONTROLALTERATEADDRESSING|VM68K_LEGAL_AM_PREDEC,&ea);
519 				// special case: the memory decrement should only be performed when the bitmask says so
520 				{
521 					for (i=0;i<8;i++) next.a[i]=pVM68k->a[i];
522 				}
523 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
524 				if (retval==VM68K_OK) bitmask=READEXTENSIONWORD(pVM68k,&next);
525 				if (retval==VM68K_OK)
526 				{
527 					for (i=0;i<8;i++)
528 					{
529 						if (bitmask&1)
530 						{
531 							// FIXME: technically not the stack.
532 							if (datatype2==VM68K_WORD) PUSHWORDTOSTACK(pVM68k,&next,pVM68k->a[7-i]);
533 							if (datatype2==VM68K_LONG) PUSHLONGTOSTACK(pVM68k,&next,pVM68k->a[7-i]);
534 						}
535 						bitmask>>=1;
536 					}
537 					for (i=0;i<8;i++)
538 					{
539 						if (bitmask&1)
540 						{
541 							// FIXME: technically not the stack.
542 							if (datatype2==VM68K_WORD) PUSHWORDTOSTACK(pVM68k,&next,pVM68k->d[7-i]);
543 							if (datatype2==VM68K_LONG) PUSHLONGTOSTACK(pVM68k,&next,pVM68k->d[7-i]);
544 						}
545 						bitmask>>=1;
546 					}
547 				}
548 			}
549 		break;
550 		case VM68K_INST_MOVEMmemtoreg:
551 			{
552 				tVM68k_types datatype2;
553 				tVM68k_uword bitmask=0;
554 				datatype2=((opcode>>6)&1)?VM68K_LONG:VM68K_WORD;
555 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_CONTROLADDRESSING|VM68K_LEGAL_AM_POSTINC,&ea);
556 				// special case: the memory increment should only be performed when the bitmask says so
557 				{
558 					for (i=0;i<8;i++) next.a[i]=pVM68k->a[i];
559 				}
560 				if (retval==VM68K_OK) bitmask=READEXTENSIONWORD(pVM68k,&next);
561 				if (retval==VM68K_OK)
562 				{
563 					for (i=0;i<8;i++)
564 					{
565 						if (bitmask&1)
566 						{
567 							// FIXME: not really the stack.
568 							if (datatype2==VM68K_WORD)
569 							{
570 								POPWORDFROMSTACK(pVM68k,&next,next.d[i]);
571 							}
572 							if (datatype2==VM68K_LONG)
573 							{
574 								POPLONGFROMSTACK(pVM68k,&next,next.d[i]);
575 							}
576 						}
577 						bitmask>>=1;
578 					}
579 					for (i=0;i<8;i++)
580 					{
581 						if (bitmask&1)
582 						{
583 							// FIXME: not really the stack.
584 							if (datatype2==VM68K_WORD)
585 							{
586 								POPWORDFROMSTACK(pVM68k,&next,next.a[i]);
587 								next.a[i]&=0xffff;
588 							}
589 							if (datatype2==VM68K_LONG)
590 							{
591 								POPLONGFROMSTACK(pVM68k,&next,next.a[i]);
592 							}
593 						}
594 						bitmask>>=1;
595 					}
596 				}
597 			}
598 		break;
599 		case VM68K_INST_EXT:
600 		{
601 			tVM68k_types datatype2=VM68K_UNKNOWN;
602 			switch ((opcode>>6)&0x3)
603 			{
604 				case 2:	datatype2=VM68K_WORD;break;
605 				case 3:	datatype2=VM68K_LONG;break;
606 			}
607 			switch (datatype2)
608 			{
609 				case VM68K_WORD:	result=(tVM68k_sword)((tVM68k_sbyte)(pVM68k->d[reg2]&  0xff));retval=VM68K_OK;
610 							result=((pVM68k->d[reg2])&0xffff0000)|(((tVM68k_ulong)result)&0xffff);
611 							break;
612 				case VM68K_LONG:	result=(tVM68k_slong)((tVM68k_sword)(pVM68k->d[reg2]&0xffff));retval=VM68K_OK;break;
613 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
614 			}
615 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype2,0,0,result);
616 			if (retval==VM68K_OK) next.d[reg2]=result;
617 		}
618 		break;
619 		case VM68K_INST_PEA:
620 			retval=vm68k_resolve_ea(pVM68k,&next,VM68K_LONG,addrmode,reg2,VM68K_LEGAL_CONTROLADDRESSING,&ea);
621 			result=ea;
622 			if (retval==VM68K_OK) PUSHLONGTOSTACK(pVM68k,&next,result);
623 		break;
624 		case VM68K_INST_LEA:
625 			retval=vm68k_resolve_ea(pVM68k,&next,VM68K_LONG,addrmode,reg2,VM68K_LEGAL_CONTROLADDRESSING,&ea);
626 			result=ea%(pVM68k->memsize);
627 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,VM68K_LONG,ADDRREGADDR(reg1),result);
628 		break;
629 		case VM68K_INST_NOP:
630 			retval=VM68K_OK;
631 		break;
632 		case VM68K_INST_ASL_ASR:
633 		case VM68K_INST_LSL_LSR:
634 		case VM68K_INST_ROL_ROR:
635 		case VM68K_INST_ROXL_ROXR:
636 		{
637 			tVM68k_types datatype2;
638 			tVM68k_ubyte count;
639 			tVM68k_bool direction;
640 			tVM68k_bool msb;
641 			tVM68k_bool lsb;
642 			tVM68k_ubyte bitnum;
643 			direction=(opcode>>8)&1;	// 0=right. 1=left.
644 			bitnum=8;
645 			if (datatype==VM68K_UNKNOWN)	// memory shift
646 			{
647 				datatype2=VM68K_WORD;
648 				count=1;
649 				retval=vm68k_resolve_ea(pVM68k,&next,VM68K_LONG,addrmode,reg2,VM68K_LEGAL_MEMORYALTERATE,&ea);
650 			} else {
651 				datatype2=datatype;
652 				if ((opcode>>5)&1)
653 				{
654 					count=pVM68k->d[reg1]%64;
655 				}
656 				else // i/r=1 -> register. i/r=0 -> immedate
657 				{
658 					count=reg1;
659 					if (count==0) count=8;
660 				}
661 				retval=VM68K_OK;
662 				ea=DATAREGADDR(reg2);
663 			}
664 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand2);
665 			switch (datatype2)
666 			{
667 				case VM68K_BYTE: bitnum= 8;break;
668 				case VM68K_WORD: bitnum=16;break;
669 				case VM68K_LONG: bitnum=32;break;
670 				default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
671 			}
672 			next.vflag=0;
673 			for (i=0;i<count;i++)
674 			{
675 				tVM68k_bool prevmsb;
676 				prevmsb=msb=(operand2>>(bitnum-1))&1;
677 				lsb=operand2&1;
678 				if (direction)	// left shift
679 				{
680 					operand2<<=1;
681 					switch (instruction)
682 					{
683 						case VM68K_INST_ASL_ASR:
684 						case VM68K_INST_LSL_LSR:	lsb=0;break;
685 						case VM68K_INST_ROL_ROR:	lsb=msb;break;
686 						case VM68K_INST_ROXL_ROXR:	lsb=next.xflag;break;
687 						default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
688 					}
689 					operand2|=lsb;
690 					next.cflag=next.xflag=msb;
691 					// FIXME: reallY???
692 					if (instruction!=VM68K_INST_ASL_ASR) next.vflag|=(prevmsb^(operand2>>(bitnum-1)))&1;	// set overflow flag if the msb is changed at any time.
693 				} else {	/// right shift
694 					operand2>>=1;
695 					switch (instruction)
696 					{
697 						case VM68K_INST_ASL_ASR:	msb=msb&1;break;
698 						case VM68K_INST_LSL_LSR:	msb=0;break;
699 						case VM68K_INST_ROL_ROR:	msb=lsb;break;
700 						case VM68K_INST_ROXL_ROXR:	msb=next.xflag;break;
701 						default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
702 					}
703 					operand2|=(msb<<(bitnum-1));
704 					next.cflag=next.xflag=lsb;
705 
706 				}
707 			}
708 			result=operand2;
709 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGN|FLAGZ,datatype2,0,operand2,result);
710 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
711 		}
712 		break;
713 		case VM68K_INST_BCLR:
714 		case VM68K_INST_BCHG:
715 		case VM68K_INST_BSET:
716 		case VM68K_INST_BTST:
717 		{
718 			tVM68k_ubyte bitnum;
719 			tVM68k_types datatype2;
720 			if (addrmode==VM68K_AM_DATAREG)
721 			{
722 				datatype2=VM68K_LONG;
723 				bitnum=32;
724 			} else {
725 				datatype2=VM68K_BYTE;
726 				bitnum=8;
727 			}
728 			retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
729 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
730 			if (retval==VM68K_OK)
731 			{
732 				operand1=(1<<(next.d[reg1]%bitnum));
733 				next.zflag=((operand2&operand1)==0);
734 
735 				switch(instruction)
736 				{
737 					case VM68K_INST_BCLR: result=operand2&~operand1;break;
738 					case VM68K_INST_BCHG: result=operand2^ operand1;break;
739 					case VM68K_INST_BSET: result=operand2| operand1;break;
740 					default:
741 							      result=0;
742 							      break;
743 				}
744 			}
745 			if (retval==VM68K_OK && instruction!=VM68K_INST_BTST) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
746 		}
747 		break;
748 		case VM68K_INST_BCLRI:
749 		case VM68K_INST_BCHGB:
750 		case VM68K_INST_BSETB:
751 		case VM68K_INST_BTSTB:
752 		{
753 			tVM68k_uword bitnum;
754 			tVM68k_types datatype2;
755 			bitnum=READEXTENSIONWORD(pVM68k,&next);
756 			datatype2=((addrmode==VM68K_AM_DATAREG)||(addrmode==VM68K_AM_ADDRREG))?VM68K_LONG:VM68K_BYTE;
757 			retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
758 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
759 			if (retval==VM68K_OK)
760 			{
761 				operand1=(1<<(bitnum%32));
762 				next.zflag=((operand2&operand1)==0);
763 				switch (instruction)
764 				{
765 					case VM68K_INST_BCLRI:	result=operand2&~operand1;break;
766 					case VM68K_INST_BCHGB:	result=operand2^ operand1;break;
767 					case VM68K_INST_BSETB:	result=operand2| operand1;break;
768 					default:
769 								result=0;
770 								break;
771 				}
772 			}
773 			if (retval==VM68K_OK && instruction!=VM68K_INST_BTSTB) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
774 
775 		}
776 		break;
777 		case VM68K_INST_ADDX:
778 		case VM68K_INST_SUBX:
779 		{
780 			tVM68k_slong ea_dest;
781 			tVM68k_bool rm;
782 
783 			rm=(opcode>>3)&1;
784 			retval=vm68k_resolve_ea(pVM68k,&next,datatype,(rm?VM68K_AM_PREDEC:VM68K_AM_DATAREG),reg2,VM68K_LEGAL_AM_PREDEC|VM68K_LEGAL_AM_DATAREG,&ea);
785 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand2);
786 			if (retval==VM68K_OK) retval=vm68k_resolve_ea(pVM68k,&next,datatype,(rm?VM68K_AM_PREDEC:VM68K_AM_DATAREG),reg1,VM68K_LEGAL_AM_PREDEC|VM68K_LEGAL_AM_DATAREG,&ea_dest);
787 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand1);
788 			if (retval==VM68K_OK) operand1+=next.xflag;
789 
790 			if (retval==VM68K_OK) if (instruction==VM68K_INST_SUBX) operand1=-operand1;
791 			if (retval==VM68K_OK) result=operand1+operand2;
792 			if (retval==VM68K_OK) if (result!=0) next.zflag=0;	// special case
793 			if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_ALL^FLAGZ,datatype,operand1,operand2,result);
794 			if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
795 
796 		}
797 		break;
798 		case VM68K_INST_CMPM:
799 		{
800 			tVM68k_slong ea_dest;
801 
802 			retval=vm68k_resolve_ea(pVM68k,&next,datatype,VM68K_AM_POSTINC,reg2,VM68K_LEGAL_AM_POSTINC,&ea);
803 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea,&operand2);
804 			if (retval==VM68K_OK) retval=vm68k_resolve_ea(pVM68k,&next,datatype,VM68K_AM_POSTINC,reg1,VM68K_LEGAL_AM_POSTINC,&ea_dest);
805 			if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,1,datatype,ea_dest,&operand1);
806 			if (retval==VM68K_OK) result=operand2-operand1;
807 			if (retval==VM68K_OK) retval=vm68k_calculateflags2(&next,FLAGS_ALL,instruction,datatype,operand1,operand2,result);
808 		}
809 		break;
810 
811 		case VM68K_INST_CLR:
812 			{
813 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
814 				result=0;
815 				if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype,0,0,result);
816 				if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype,ea,result);
817 
818 			}
819 		break;
820 		case VM68K_INST_DBcc:
821 			{
822 				retval=VM68K_OK;
823 				displacement=READEXTENSIONWORD(pVM68k,&next);
824 				if (!vm68k_checkcondition(pVM68k,condition))
825 				{
826 					next.d[reg2]&=0xffff0000;
827 					next.d[reg2]|=(pVM68k->d[reg2]-1)&0xffff;
828 					if ((tVM68k_sword)next.d[reg2]>=0) next.pcr=pVM68k->pcr+displacement;
829 				}
830 			}
831 		break;
832 		case VM68K_INST_SWAP:
833 			{
834 				tVM68k_types datatype2;
835 				datatype2=VM68K_LONG;
836 
837 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,VM68K_AM_DATAREG,reg2,VM68K_LEGAL_AM_DATAREG,&ea);
838 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype2,ea,&operand2);
839 				if (retval==VM68K_OK) result=((operand2>>16)&0xffff)|((operand2&0xffff)<<16);
840 				if (retval==VM68K_OK) next.nflag=(result>>31)&1;
841 				if (retval==VM68K_OK) next.zflag=(result==0);
842 				next.cflag=0;
843 				next.vflag=0;
844 				if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
845 
846 			}
847 		break;
848 		case VM68K_INST_SCC:
849 			{
850 				tVM68k_types datatype2;
851 				datatype2=VM68K_BYTE;
852 				result=(vm68k_checkcondition(pVM68k,condition))?0xff:0x00;
853 				retval=vm68k_resolve_ea(pVM68k,&next,datatype2,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
854 				if (retval==VM68K_OK) retval=vm68k_storeresult(pVM68k,&next,datatype2,ea,result);
855 			}
856 		break;
857 		case VM68K_INST_TST:
858 			{
859 				retval=vm68k_resolve_ea(pVM68k,&next,datatype,addrmode,reg2,VM68K_LEGAL_DATAALTERATE,&ea);
860 				if (retval==VM68K_OK) retval=vm68k_fetchoperand(pVM68k,0,datatype,ea,&operand2);
861 				if (retval==VM68K_OK) result=operand2;
862 				if (retval==VM68K_OK) retval=vm68k_calculateflags(&next,FLAGS_LOGIC,datatype,0,0,result);
863 
864 			}
865 		break;
866 		case VM68K_INST_UNKNOWN:
867 			retval=VM68K_NOK_UNKNOWN_INSTRUCTION;
868 		break;
869 		default:
870 		{
871 #ifdef	DEBUG_PRINT
872 			char tmp[64];
873 			vm68k_get_instructionname(instruction,tmp);
874 			printf("UNIMPLEMENTED opcode %04X = %s\n",opcode,tmp);
875 #else
876 			printf("UNIMPLEMENTED opcode %04X\n",opcode);
877 #endif
878 			retval=VM68K_NOK_UNKNOWN_INSTRUCTION;
879 		}
880 		break;
881 	}
882 	if (retval==VM68K_OK)
883 	{
884 		pVM68k->pcr=next.pcr;
885 		pVM68k->sr&=0xffe0;
886 		if (next.override_sr==1)
887 		{
888 			pVM68k->sr=next.sr;
889 		} else {
890 			pVM68k->sr|=(next.cflag)<<0;
891 			pVM68k->sr|=(next.vflag)<<1;
892 			pVM68k->sr|=(next.zflag)<<2;
893 			pVM68k->sr|=(next.nflag)<<3;
894 			pVM68k->sr|=(next.xflag)<<4;
895 		}
896 		for (i=0;i<8;i++)
897 		{
898 			pVM68k->a[i]=next.a[i];
899 			pVM68k->d[i]=next.d[i];
900 		}
901 		if (next.mem_we)
902 		{
903 			for (i=0;i<next.mem_we;i++)
904 			{
905 #ifdef	DEBUG_PRINT
906 				if (next.mem_size==VM68K_WORD) printf("\n\nMEMWRITE WORD %04X @ %04x\n",(next.mem_value[i])&0xffff,next.mem_addr[i]);
907 				if (next.mem_size==VM68K_LONG) printf("\n\nMEMWRITE LONG %08X @ %04x\n",next.mem_value[i],next.mem_addr[i]);
908 		fflush(stdout);
909 #endif
910 				switch(next.mem_size)
911 				{
912 					case 0:	WRITE_INT8BE(pVM68k->pMem, next.mem_addr[i],next.mem_value[i]&      0xff);break;
913 					case 1:	WRITE_INT16BE(pVM68k->pMem,next.mem_addr[i],next.mem_value[i]&    0xffff);break;
914 					case 2:	WRITE_INT32BE(pVM68k->pMem,next.mem_addr[i],next.mem_value[i]&0xffffffff);break;
915 					default: retval=VM68K_NOK_UNKNOWN_INSTRUCTION;break;
916 				}
917 			}
918 		}
919 	}
920 
921 	return	retval;
922 }
vm68k_getNextOpcode(void * hVM68k,unsigned short * opcode)923 int vm68k_getNextOpcode(void* hVM68k,unsigned short* opcode)
924 {
925 
926 	tVM68k* pVM68k=(tVM68k*)hVM68k;
927 	if (hVM68k==NULL) return VM68K_NOK_INVALID_PTR;
928 	if (opcode==NULL) return VM68K_NOK_INVALID_PTR;
929 	if (pVM68k->magic!=MAGICVALUE) return VM68K_NOK_INVALID_PARAMETER;
930 	*opcode=READ_INT16BE(pVM68k->pMem,pVM68k->pcr);
931 	pVM68k->pcr+=2;
932 #ifdef	DEBUG_PRINT
933 	{
934 		int i;
935 		char tmp[64];
936 		tVM68k_instruction inst;
937 		printf("\n\n\n");
938 		printf("pcr:%06x ",pVM68k->pcr);
939 		printf("INST:%04X ",*opcode);
940 		printf("CVZN:%d%d%d%d ", (pVM68k->sr>>0)&1,(pVM68k->sr>>1)&1,(pVM68k->sr>>2)&1,(pVM68k->sr>>3)&1);
941 		printf("D:");
942 		for (i=0;i<8;i++)
943 		{
944 			printf("%08X:",pVM68k->d[i]);
945 		}
946 		printf(" A:");
947 		for (i=0;i<8;i++)
948 		{
949 			printf("%08X:",pVM68k->a[i]);
950 		}
951 
952 		{
953 			unsigned long long sum;
954 			sum=0;
955 			for (i=0;i<pVM68k->memsize;i++) sum+=READ_INT32BE(pVM68k->pMem,i);
956 			printf("MEMSUM:%llX ",sum);
957 		}
958 		inst=vm68k_decode(*opcode);
959 		vm68k_get_instructionname(inst,tmp);
960 		printf(" --> %s\n",tmp);
961 		if (pVM68k->pcr<0x1c238) printf("\x1b[0m\n");
962 		fflush(stdout);
963 	}
964 #endif
965 
966 	return VM68K_OK;
967 }
968