1 /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2 
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 
7 #include "generator.h"
8 #include "cpu68k.h"
9 #include "mem68k.h"
10 #include "def68k-iibs.h"
11 #include "def68k-proto.h"
12 #include "def68k-funcs.h"
13 
14 int diss68k_gettext(t_ipc * ipc, char *text);
15 
16 /*** externed variables ***/
17 
18 uint8 *cpu68k_rom = NULL;
19 unsigned int cpu68k_romlen = 0;
20 uint8 *cpu68k_ram = NULL;
21 t_iib *cpu68k_iibtable[65536];
22 void (*cpu68k_functable[65536 * 2]) (t_ipc * ipc);
23 int cpu68k_totalinstr;
24 int cpu68k_totalfuncs;
25 
26 unsigned int cpu68k_clocks;
27 unsigned int cpu68k_frames;
28 unsigned int cpu68k_frozen;     /* cpu frozen, do not interrupt, make pending */
29 t_regs regs;
30 uint8 movem_bit[256];
31 t_ipclist *ipclist[LEN_IPCLISTTABLE];
32 
33 //extern uint8 current_cpu_bank;
34 extern uint32 bankaddress;
35 
36 /*** global variables ***/
37 
38 /*** forward references ***/
39 
40 void cpu68k_reset(void);
41 
cpu68k_init(void)42 int cpu68k_init(void)
43 {
44   t_iib *iib;
45   uint16 bitmap;
46   int i, j, sbit, dbit, sbits, dbits;
47 
48   memset(cpu68k_iibtable, 0, sizeof(cpu68k_iibtable));
49   memset(cpu68k_functable, 0, sizeof(cpu68k_functable));
50   memset(&regs, 0, sizeof(regs));
51 
52   cpu68k_frozen = 0;
53   cpu68k_totalinstr = 0;
54 
55   for (i = 0; i < iibs_num; i++) {
56     iib = &iibs[i];
57 
58     bitmap = iib->mask;
59     sbits = 0;
60     dbits = 0;
61 
62     for (j = 0; j < 2; j++) {
63       switch (j ? iib->stype : iib->dtype) {
64       case dt_Dreg:
65       case dt_Areg:
66       case dt_Aind:
67       case dt_Ainc:
68       case dt_Adec:
69       case dt_Adis:
70       case dt_Aidx:
71         if (j) {
72           bitmap ^= 7 << iib->sbitpos;
73           sbits = 3;
74         } else {
75           bitmap ^= 7 << iib->dbitpos;
76           dbits = 3;
77         }
78         break;
79       case dt_AbsW:
80       case dt_AbsL:
81       case dt_Pdis:
82       case dt_Pidx:
83         break;
84       case dt_ImmB:
85       case dt_ImmW:
86       case dt_ImmL:
87       case dt_ImmS:
88         break;
89       case dt_Imm3:
90         if (j) {
91           bitmap ^= 7 << iib->sbitpos;
92           sbits = 3;
93         } else {
94           bitmap ^= 7 << iib->dbitpos;
95           dbits = 3;
96         }
97         break;
98       case dt_Imm4:
99         if (j) {
100           bitmap ^= 15 << iib->sbitpos;
101           sbits = 4;
102         } else {
103           bitmap ^= 15 << iib->dbitpos;
104           dbits = 4;
105         }
106         break;
107       case dt_Imm8:
108       case dt_Imm8s:
109         if (j) {
110           bitmap ^= 255 << iib->sbitpos;
111           sbits = 8;
112         } else {
113           bitmap ^= 255 << iib->dbitpos;
114           dbits = 8;
115         }
116         break;
117       case dt_ImmV:
118         sbits = 12;
119         bitmap ^= 0x0FFF;
120         break;
121       case dt_Ill:
122         /* no src/dst parameter */
123         break;
124       default:
125         LOG_CRITICAL(("CPU definition #%d incorrect", i));
126         return 1;
127       }
128     }
129     if (bitmap != 0xFFFF) {
130       LOG_CRITICAL(("CPU definition #%d incorrect (0x%x)", i, bitmap));
131       return 1;
132     }
133     for (sbit = 0; sbit < (1 << sbits); sbit++) {
134       for (dbit = 0; dbit < (1 << dbits); dbit++) {
135         bitmap = iib->bits | (sbit << iib->sbitpos) | (dbit << iib->dbitpos);
136         if (iib->stype == dt_Imm3 || iib->stype == dt_Imm4
137             || iib->stype == dt_Imm8) {
138           if (sbit == 0 && iib->flags.imm_notzero) {
139             continue;
140           }
141         }
142         if (cpu68k_iibtable[bitmap] != NULL) {
143           LOG_CRITICAL(("CPU definition #%d conflicts (0x%x)", i, bitmap));
144           return 1;
145         }
146         cpu68k_iibtable[bitmap] = iib;
147         /* set both flag and non-flag versions */
148         cpu68k_functable[bitmap * 2] = cpu68k_funcindex[i * 2];
149         cpu68k_functable[bitmap * 2 + 1] = cpu68k_funcindex[i * 2 + 1];
150         cpu68k_totalinstr++;
151       }
152     }
153   }
154 
155   j = 0;
156 
157   for (i = 0; i < 65536; i++) {
158     if (cpu68k_iibtable[i]) {
159       j++;
160     }
161   }
162   if (j != cpu68k_totalinstr) {
163     LOG_CRITICAL(("Instruction count not verified (%d/%d)\n",
164                   cpu68k_totalinstr, i));
165     return 1;
166   }
167 
168   cpu68k_totalfuncs = iibs_num;
169 
170   for (i = 0; i < 256; i++) {
171     for (j = 0; j < 8; j++) {
172       if (i & (1 << j))
173         break;
174     }
175     movem_bit[i] = j;
176   }
177 
178   LOG_VERBOSE(("CPU: %d instructions supported by %d routines",
179                cpu68k_totalinstr, cpu68k_totalfuncs));
180   iib = cpu68k_iibtable[0x2F39];
181   return 0;
182 }
183 
cpu68k_printipc(t_ipc * ipc)184 void cpu68k_printipc(t_ipc * ipc)
185 {
186     static char dasmtxt[256];
187   printf("IPC @ 0x%p\n", ipc);
188   diss68k_gettext(ipc,dasmtxt);
189   printf("%s\n",dasmtxt);
190   printf("  opcode: %04X, uses %X set %X\n", ipc->opcode, ipc->used,
191          ipc->set);
192   printf("  src = %08X\n", (unsigned)ipc->src);
193   printf("  dst = %08X\n", (unsigned)ipc->dst);
194 }
195 
196 /* fill in ipc */
197 
cpu68k_ipc(uint32 addr68k,uint8 * addr,t_iib * iib,t_ipc * ipc)198 void cpu68k_ipc(uint32 addr68k, uint8 *addr, t_iib * iib, t_ipc * ipc)
199 {
200   t_type type;
201   uint32 *p;
202 
203   ipc->opcode = LOCENDIAN16(*(uint16 *)addr);
204   ipc->wordlen = 1;
205   if (!iib) {
206     /* illegal instruction, no further details (wordlen must be set to 1) */
207     return;
208   }
209 
210   ipc->used = iib->flags.used;
211   ipc->set = iib->flags.set;
212 
213   if ((iib->mnemonic == i_Bcc) || (iib->mnemonic == i_BSR)) {
214     /* special case - we can calculate the offset now */
215     /* low 8 bits of current instruction are addr+1 */
216     ipc->src = (sint32)(*(sint8 *)(addr + 1));
217     if (ipc->src == 0) {
218       ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr + 2));
219       ipc->wordlen++;
220     }
221     ipc->src += addr68k + 2;    /* add PC of next instruction */
222     return;
223   }
224   if (iib->mnemonic == i_DBcc || iib->mnemonic == i_DBRA) {
225     /* special case - we can calculate the offset now */
226     ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr + 2));
227     ipc->src += addr68k + 2;    /* add PC of next instruction */
228     ipc->wordlen++;
229     return;
230   }
231 
232   addr += 2;
233   addr68k += 2;
234 
235   for (type = 0; type < 2; type++) {
236     if (type == tp_src)
237       p = &(ipc->src);
238     else
239       p = &(ipc->dst);
240 
241     switch (type == tp_src ? iib->stype : iib->dtype) {
242     case dt_Adis:
243       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
244       ipc->wordlen++;
245       addr += 2;
246       addr68k += 2;
247       break;
248     case dt_Aidx:
249       *p = (sint32)(sint8)addr[1];
250       *p = (*p & 0xFFFFFF) | (*addr) << 24;
251       ipc->wordlen++;
252       addr += 2;
253       addr68k += 2;
254       break;
255     case dt_AbsW:
256       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
257       ipc->wordlen++;
258       addr += 2;
259       addr68k += 2;
260       break;
261     case dt_AbsL:
262       *p = (uint32)((LOCENDIAN16(*(uint16 *)addr) << 16) +
263                     LOCENDIAN16(*(uint16 *)(addr + 2)));
264       ipc->wordlen += 2;
265       addr += 4;
266       addr68k += 4;
267       break;
268     case dt_Pdis:
269       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
270       *p += addr68k;            /* add PC of extension word (this word) */
271       ipc->wordlen++;
272       addr += 2;
273       addr68k += 2;
274       break;
275     case dt_Pidx:
276       *p = ((sint32)(sint8)addr[1]) + addr68k;
277       *p = (*p & 0xFFFFFF) | (*addr) << 24;
278       ipc->wordlen++;
279       addr += 2;
280       addr68k += 2;
281       break;
282     case dt_ImmB:
283       /* low 8 bits of next 16 bit word is addr+1 */
284       *p = (uint32)(*(uint8 *)(addr + 1));
285       ipc->wordlen++;
286       addr += 2;
287       addr68k += 2;
288       break;
289     case dt_ImmW:
290       *p = (uint32)LOCENDIAN16(*(uint16 *)addr);
291       ipc->wordlen++;
292       addr += 2;
293       addr68k += 2;
294       break;
295     case dt_ImmL:
296       *p = (uint32)((LOCENDIAN16(*(uint16 *)addr) << 16) +
297                     LOCENDIAN16(*(uint16 *)(addr + 2)));
298       ipc->wordlen += 2;
299       addr += 4;
300       addr68k += 4;
301       break;
302     case dt_Imm3:
303       if (type == tp_src)
304         *p = (ipc->opcode >> iib->sbitpos) & 7;
305       else
306         *p = (ipc->opcode >> iib->dbitpos) & 7;
307       break;
308     case dt_Imm4:
309       if (type == tp_src)
310         *p = (ipc->opcode >> iib->sbitpos) & 15;
311       else
312         *p = (ipc->opcode >> iib->dbitpos) & 15;
313       break;
314     case dt_Imm8:
315       if (type == tp_src)
316         *p = (ipc->opcode >> iib->sbitpos) & 255;
317       else
318         *p = (ipc->opcode >> iib->dbitpos) & 255;
319       break;
320     case dt_Imm8s:
321       if (type == tp_src)
322         *p = (sint32)(sint8)((ipc->opcode >> iib->sbitpos) & 255);
323       else
324         *p = (sint32)(sint8)((ipc->opcode >> iib->dbitpos) & 255);
325       break;
326     default:
327       break;
328     }
329   }
330 }
331 
cpu68k_makeipclist(uint32 pc)332 t_ipclist *cpu68k_makeipclist(uint32 pc)
333 {
334   int size = 16;
335   t_ipclist *list = malloc(sizeof(t_ipclist) + 16 * sizeof(t_ipc) + 8);
336   t_ipc *ipc = (t_ipc *) (list + 1);
337   t_iib *iib;
338   int instrs = 0;
339   uint16 required;
340   int i;
341 
342   if (list == NULL) {
343       printf("Out of memory");
344       exit(1);
345   }
346 
347   pc &= 0xffffff;
348   list->pc = pc;
349   list->clocks = 0;
350   list->norepeat = 0;
351 
352   if ((pc&0xF00000)==0x200000)
353       list->bank = bankaddress;
354   else
355        list->bank = 0;
356 
357 
358   do {
359     instrs++;
360     if (instrs > size) {
361 	if (size > 10000) {
362 	    printf("Something has gone seriously wrong @ %08X", (unsigned)pc);
363 	    exit(1);
364 	}
365 	size += 16;
366 	list = realloc(list, sizeof(t_ipclist) + size * sizeof(t_ipc) + 8);
367 	if (list == NULL) {
368 	    printf("Out of memory whilst making ipc list @ %08X",
369 		(unsigned)pc);
370 	    exit(1);
371 	}
372 	ipc = ((t_ipc *) (list + 1)) + instrs - 1;
373     }
374     if (!(iib = cpu68k_iibtable[fetchword(pc)])) {
375 	printf("Invalid instruction @ %08X [%04X]", (unsigned)pc,
376 	    fetchword(pc));
377 	exit(1);
378     }
379     cpu68k_ipc(pc, mem68k_memptr[pc >> 12] (pc), iib, ipc);
380     list->clocks += iib->clocks;
381     pc += (iib->wordlen) << 1;
382     ipc++;
383   }
384   while (!iib->flags.endblk);
385   *(int *)ipc = 0;
386 
387   if (instrs == 2) {
388     ipc--;
389     if (iib->mnemonic == i_Bcc && ipc->src == list->pc) {
390       /* we have a 2-instruction block ending in a branch to start */
391       ipc = (t_ipc *) (list + 1);
392       iib = cpu68k_iibtable[ipc->opcode];
393       if (iib->mnemonic == i_TST || iib->mnemonic == i_CMP) {
394         /* it's a tst/cmp and then a Bcc */
395         if (!(iib->stype == dt_Ainc || iib->stype == dt_Adec)) {
396           /* no change could happen during the block */
397           list->norepeat = 1;
398         }
399       }
400     }
401   }
402 
403   ipc = ((t_ipc *) (list + 1)) + instrs - 1;
404   required = 0x1F;              /* all 5 flags need to be correct at end */
405   for (i = 0; i < instrs; i++) {
406     ipc->set &= required;
407     required &= ~ipc->set;
408     required |= ipc->used;
409     if (ipc->set) {
410       ipc->function = cpu68k_functable[(ipc->opcode << 1) + 1];
411     } else {
412       ipc->function = cpu68k_functable[ipc->opcode << 1];
413     }
414     ipc--;
415   }
416   /* fprintf("Cached %08X to %08X\n", list->pc, pc-((iib->wordlen)<<1)); */
417   return list;
418 }
419 
cpu68k_clearcache(void)420 void cpu68k_clearcache(void)
421 {
422   int i;
423   t_ipclist *p, *n;
424 
425   for (i = 0; i < LEN_IPCLISTTABLE; i++) {
426     if (ipclist[i]) {
427       p=ipclist[i];
428       while(p){
429         n=p->next;
430         free(p);
431     p=n;
432       }
433       ipclist[i] = NULL;
434     }
435   }
436 }
437 
cpu68k_reset(void)438 void cpu68k_reset(void)
439 {
440   int i;
441   t_ipclist *p, *n;
442 #if 0
443   if (!cpu68k_ram) {
444     /* +4 due to bug in DIRECTRAM hdr/mem68k.h code over-run of buffer */
445     if ((cpu68k_ram = malloc(0x10000 + 4)) == NULL)
446       ui_err("Out of memory");
447   }
448   memset(cpu68k_ram, 0, 0x10000);
449 #endif
450 
451   regs.pc = fetchlong(4);
452   regs.regs[15] = fetchlong(0);
453   regs.sr.sr_int = 0;
454   regs.sr.sr_struct.s = 1;      /* Supervisor mode */
455   regs.stop = 0;
456   cpu68k_clocks = 0;
457   cpu68k_frames = 0;            /* Number of frames */
458 
459   for (i = 0; i < LEN_IPCLISTTABLE; i++) {
460     if (ipclist[i]) {
461       p=ipclist[i];
462       while(p){
463         n=p->next;
464         free(p);
465     p=n;
466       }
467       ipclist[i] = NULL;
468     }
469   }
470 }
471 
cpu68k_endfield(void)472 void cpu68k_endfield(void)
473 {
474   cpu68k_clocks = 0;
475 }
476