Annotation of generator/main/cpu68k.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.