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

1.1       root        1: /*****************************************************************************/
                      2: /*     Generator - Sega Genesis emulation - (c) James Ponder 1997-1998       */
                      3: /*****************************************************************************/
                      4: /*                                                                           */
                      5: /* cpu68k.c                                                                  */
                      6: /*                                                                           */
                      7: /*****************************************************************************/
                      8: 
                      9: #include <stdio.h>
                     10: #include <string.h>
                     11: #include <stdlib.h>
                     12: 
                     13: #include "generator.h"
                     14: #include "mem68k.h"
                     15: #include "cpu68k.h"
                     16: #include "vdp.h"
                     17: #include "ui.h"
                     18: #include "out/def68k-iibs.h"
                     19: #include "out/def68k-proto.h"
                     20: #include "out/def68k-funcs.h"
                     21: 
                     22: /*** externed variables ***/
                     23: 
                     24: uint8 *cpu68k_rom = NULL;
                     25: unsigned int cpu68k_romlen = 0;
                     26: uint8 *cpu68k_ram = NULL;
                     27: t_iib *cpu68k_iibtable[65536];
                     28: void (*cpu68k_functable[65536*2])(t_ipc *ipc);
                     29: int cpu68k_totalinstr;
                     30: int cpu68k_totalfuncs;
                     31: unsigned int cpu68k_clocks;
                     32: unsigned int cpu68k_frames;
                     33: t_regs regs;
                     34: uint8 movem_bit[256];
                     35: t_ipclist *ipclist[LEN_IPCLISTTABLE];
                     36: 
                     37: /*** global variables ***/
                     38: 
                     39: /*** forward references ***/
                     40: 
                     41: void cpu68k_reset(void);
                     42: 
                     43: int cpu68k_init(void)
                     44: {
                     45:   t_iib *iib;
                     46:   uint16 bitmap;
                     47:   int i, j, sbit, dbit, sbits, dbits;
                     48: 
                     49:   memset(cpu68k_iibtable, 0, sizeof(cpu68k_iibtable));
                     50:   memset(cpu68k_functable, 0, sizeof(cpu68k_functable));
                     51:   memset(&regs, 0, sizeof(regs));
                     52: 
                     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: 
                    181:   return 0;
                    182: }
                    183: 
                    184: /* fill in ipc */
                    185: 
                    186: void cpu68k_ipc(uint32 addr68k, uint8 *addr, t_iib *iib, t_ipc *ipc)
                    187: {
                    188:   t_type type;
                    189:   uint32 *p;
                    190: 
                    191:   ipc->opcode = LOCENDIAN16(*(uint16 *)addr);
                    192:   ipc->wordlen = 1;
                    193:   if (!iib) {
                    194:     /* illegal instruction, no further details (wordlen must be set to 1) */
                    195:     return;
                    196:   }
                    197: 
                    198:   ipc->used = iib->flags.used;
                    199:   ipc->set = iib->flags.set;
                    200: 
                    201:   if ((iib->mnemonic == i_Bcc) || (iib->mnemonic == i_BSR)) {
                    202:     /* special case - we can calculate the offset now */
                    203:     /* low 8 bits of current instruction are addr+1 */
                    204:     ipc->src = (sint32)(*(sint8 *)(addr+1));
                    205:     if (ipc->src == 0) {
                    206:       ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr+2));
                    207:       ipc->wordlen++;
                    208:     }
                    209:     ipc->src+= addr68k+2; /* add PC of next instruction */
                    210:     return;
                    211:   }
                    212:   if (iib->mnemonic == i_DBcc || iib->mnemonic == i_DBRA) {
                    213:     /* special case - we can calculate the offset now */
                    214:     ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr+2));
                    215:     ipc->src+= addr68k+2; /* add PC of next instruction */
                    216:     ipc->wordlen++;
                    217:     return;
                    218:   }
                    219: 
                    220:   addr+= 2;
                    221:   addr68k+= 2;
                    222: 
                    223:   for (type = 0; type < 2; type++) {
                    224: 
                    225:     if (type == tp_src)
                    226:       p = &(ipc->src);
                    227:     else
                    228:       p = &(ipc->dst);
                    229: 
                    230:     switch(type == tp_src ? iib->stype : iib->dtype) {
                    231:     case dt_Adis:
                    232:       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
                    233:       ipc->wordlen++;
                    234:       addr+= 2;
                    235:       addr68k+= 2;
                    236:       break;
                    237:     case dt_Aidx:
                    238:       *p = (sint32)(sint8)addr[1];
                    239:       *p = (*p & 0xFFFFFF) | (*addr)<<24;
                    240:       ipc->wordlen++;
                    241:       addr+= 2;
                    242:       addr68k+= 2;
                    243:       break;
                    244:     case dt_AbsW:
                    245:       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
                    246:       ipc->wordlen++;
                    247:       addr+= 2;
                    248:       addr68k+= 2;
                    249:       break;
                    250:     case dt_AbsL:
                    251:       *p = (uint32)( (LOCENDIAN16(*(uint16 *)addr)<<16) +
                    252:                     LOCENDIAN16(*(uint16 *)(addr+2)) );
                    253:       ipc->wordlen+= 2;
                    254:       addr+= 4;
                    255:       addr68k+= 4;
                    256:       break;
                    257:     case dt_Pdis:
                    258:       *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
                    259:       *p+= addr68k; /* add PC of extension word (this word) */
                    260:       ipc->wordlen++;
                    261:       addr+= 2;
                    262:       addr68k+= 2;
                    263:       break;
                    264:     case dt_Pidx:
                    265:       *p = ((sint32)(sint8)addr[1]) + addr68k;
                    266:       *p = (*p & 0xFFFFFF) | (*addr)<<24;
                    267:       ipc->wordlen++;
                    268:       addr+= 2;
                    269:       addr68k+= 2;
                    270:       break;
                    271:     case dt_ImmB:
                    272:       /* low 8 bits of next 16 bit word is addr+1 */
                    273:       *p = (uint32)(*(uint8 *)(addr+1));
                    274:       ipc->wordlen++;
                    275:       addr+= 2;
                    276:       addr68k+= 2;
                    277:       break;
                    278:     case dt_ImmW:
                    279:       *p = (uint32)LOCENDIAN16(*(uint16 *)addr);
                    280:       ipc->wordlen++;
                    281:       addr+= 2;
                    282:       addr68k+= 2;
                    283:       break;
                    284:     case dt_ImmL:
                    285:       *p = (uint32)( (LOCENDIAN16(*(uint16 *)addr)<<16) +
                    286:                     LOCENDIAN16(*(uint16 *)(addr+2)) );
                    287:       ipc->wordlen+= 2;
                    288:       addr+= 4;
                    289:       addr68k+= 4;
                    290:       break;
                    291:     case dt_Imm3:
                    292:       if (type == tp_src)
                    293:        *p = (ipc->opcode >> iib->sbitpos) & 7;
                    294:       else
                    295:        *p = (ipc->opcode >> iib->dbitpos) & 7;
                    296:       break;
                    297:     case dt_Imm4:
                    298:       if (type == tp_src)
                    299:        *p = (ipc->opcode >> iib->sbitpos) & 15;
                    300:       else
                    301:        *p = (ipc->opcode >> iib->dbitpos) & 15;
                    302:       break;
                    303:     case dt_Imm8:
                    304:       if (type == tp_src)
                    305:        *p = (ipc->opcode >> iib->sbitpos) & 255;
                    306:       else
                    307:        *p = (ipc->opcode >> iib->dbitpos) & 255;
                    308:       break;
                    309:     case dt_Imm8s:
                    310:       if (type == tp_src)
                    311:        *p = (sint32)(sint8)((ipc->opcode >> iib->sbitpos) & 255);
                    312:       else
                    313:        *p = (sint32)(sint8)((ipc->opcode >> iib->dbitpos) & 255);
                    314:       break;
                    315:     default:
                    316:       break;
                    317:     }
                    318:   }
                    319: }
                    320: 
                    321: t_ipclist *cpu68k_makeipclist(uint32 pc)
                    322: {
                    323:   int size = 16;
                    324:   t_ipclist *list = malloc(sizeof(t_ipclist) + 16*sizeof(t_ipc) + 8);
                    325:   t_ipc *ipc = (t_ipc *)(list+1);
                    326:   t_iib *iib;
                    327:   int instrs = 0;
                    328:   uint16 required;
                    329:   int i;
                    330: 
                    331:   if (list == NULL)
                    332:     ui_err("Out of memory");
                    333: 
                    334:   pc&= 0xffffff;
                    335:   list->pc = pc;
                    336:   list->clocks = 0;
                    337:   list->norepeat = 0;
                    338:   do {
                    339:     instrs++;
                    340:     if (instrs > size) {
                    341:       size+= 16;
                    342:       list = realloc(list, sizeof(t_ipclist) + size*sizeof(t_ipc) + 8);
                    343:       ipc = ((t_ipc *)(list+1))+instrs-1;
                    344:     }
                    345:     if (!(iib = cpu68k_iibtable[fetchword(pc)])) {
                    346:       ui_err("Invalid instruction @ %08X", pc);
                    347:     }
                    348:     cpu68k_ipc(pc, mem68k_memptr[pc>>12](pc), iib, ipc);
                    349:     list->clocks+= iib->clocks;
                    350:     pc+= (iib->wordlen)<<1;
                    351:     ipc++;
                    352:   } while (!iib->flags.endblk);
                    353:   *(int *)ipc = 0;
                    354: 
                    355:   if (instrs == 2) {
                    356:     ipc--;
                    357:     if (iib->mnemonic == i_Bcc && ipc->src == list->pc) {
                    358:       /* we have a 2-instruction block ending in a branch to start */
                    359:       ipc = (t_ipc *)(list+1);
                    360:       iib = cpu68k_iibtable[ipc->opcode];
                    361:       if (iib->mnemonic == i_TST || iib->mnemonic == i_CMP) {
                    362:        /* it's a tst/cmp and then a Bcc */
                    363:        if (!(iib->stype == dt_Ainc || iib->stype == dt_Adec)) {
                    364:          /* no change could happen during the block */
                    365:          list->norepeat = 1;
                    366:        }
                    367:       }
                    368:     }
                    369:   }
                    370: 
                    371:   ipc = ((t_ipc *)(list+1))+instrs-1;
                    372:   required = 0x1F;               /* all 5 flags need to be correct at end */
                    373:   for (i = 0; i < instrs; i++) {
                    374:     ipc->set&= required;
                    375:     required&= ~ipc->set;
                    376:     required|= ipc->used;
                    377:     if (ipc->set) {
                    378:       ipc->function = cpu68k_functable[(ipc->opcode<<1)+1];
                    379:     } else {
                    380:       ipc->function = cpu68k_functable[ipc->opcode<<1];
                    381:     }
                    382:     ipc--;
                    383:   }
                    384:   /* fprintf("Cached %08X to %08X\n", list->pc, pc-((iib->wordlen)<<1)); */
                    385:   return list;
                    386: }
                    387: 
                    388: void cpu68k_reset(void)
                    389: {
                    390:   int i;
                    391: 
                    392:   if (!cpu68k_ram) {
                    393:     if ((cpu68k_ram = malloc(0x10000)) == NULL)
                    394:       ui_err("Out of memory");
                    395:   }
                    396:   memset(cpu68k_ram, 0, 0x10000);
                    397: 
                    398:   regs.pc = fetchlong(4);
                    399:   regs.regs[15] = fetchlong(0);
                    400:   regs.sr.sr_int = 0;
                    401:   regs.sr.sr_struct.s = 1; /* Supervisor mode*/
                    402:   regs.stop = 0;
                    403:   cpu68k_clocks = 0; 
                    404:   cpu68k_frames = 0; /* Number of frames */
                    405: 
                    406:   for (i = 0; i < LEN_IPCLISTTABLE; i++) {
                    407:     if (ipclist[i]) {
                    408:       free(ipclist[i]);
                    409:       ipclist[i] = NULL;
                    410:     }
                    411:   }
                    412: }
                    413: 
                    414: void cpu68k_endfield(void)
                    415: {
                    416:   cpu68k_clocks = 0;
                    417: }

unix.superglobalmegacorp.com

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