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