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

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

unix.superglobalmegacorp.com

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