Annotation of generator/src/cpu68k.c, revision 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.