main.cpp

来自「motorola ezx 平台下的fba模拟器」· C++ 代码 · 共 633 行 · 第 1/2 页

CPP
633
字号
  if (type==1) ot("write");
  if (type==2) ot("fetch");

  if (type==1) ot("%d(r0,r1)",8<<size);
  else         ot("%d(r0)",   8<<size);
  ot(" handler\n");

#if MEMHANDLERS_CHANGE_CYCLES
  ot("  ldr r5,[r7,#0x5c] ;@ Load Cycles\n");
#endif
#if MEMHANDLERS_CHANGE_FLAGS
  ot("  ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");
  ot("  mov r9,r9,lsl #28\n");
#endif
#if MEMHANDLERS_CHANGE_PC
  ot("  ldr r4,[r7,#0x40] ;@ Load PC\n");
#endif

  return 0;
}

static void PrintOpcodes()
{
  int op=0;
 
  printf("Creating Opcodes: [");

  ot(";@ ---------------------------- Opcodes ---------------------------\n");

  // Emit null opcode:
  ot("Op____%s ;@ Called if an opcode is not recognised\n", ms?"":":");
  ot("  sub r4,r4,#2\n");
#if USE_UNRECOGNIZED_CALLBACK
  ot("  str r4,[r7,#0x40] ;@ Save PC\n");
  ot("  mov r1,r9,lsr #28\n");
  ot("  strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n");
  ot("  str r5,[r7,#0x5c] ;@ Save Cycles\n");
  ot("  ldr r11,[r7,#0x94] ;@ UnrecognizedCallback\n");
  ot("  tst r11,r11\n");
  ot("  movne lr,pc\n");
  ot("  movne pc,r11 ;@ call UnrecognizedCallback if it is defined\n");
  ot("  ldr r5,[r7,#0x5c] ;@ Load Cycles\n");
  ot("  ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");
  ot("  mov r9,r9,lsl #28\n");
  ot("  ldr r4,[r7,#0x40] ;@ Load PC\n");
  ot("  tst r0,r0\n");
  ot("  moveq r0,#0x10\n");
  ot("  bleq Exception\n");
#else
  ot("  mov r0,#0x10\n");
  ot("  bl Exception\n");
#endif
  Cycles=34;
  OpEnd();

  // Unrecognised a-line and f-line opcodes throw an exception:
  ot("Op__al%s ;@ Unrecognised a-line opcode\n", ms?"":":");
  ot("  sub r4,r4,#2\n");
#if USE_AFLINE_CALLBACK
  ot("  str r4,[r7,#0x40] ;@ Save PC\n");
  ot("  mov r1,r9,lsr #28\n");
  ot("  strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n");
  ot("  str r5,[r7,#0x5c] ;@ Save Cycles\n");
  ot("  ldr r11,[r7,#0x94] ;@ UnrecognizedCallback\n");
  ot("  tst r11,r11\n");
  ot("  movne lr,pc\n");
  ot("  movne pc,r11 ;@ call UnrecognizedCallback if it is defined\n");
  ot("  ldr r5,[r7,#0x5c] ;@ Load Cycles\n");
  ot("  ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");
  ot("  mov r9,r9,lsl #28\n");
  ot("  ldr r4,[r7,#0x40] ;@ Load PC\n");
  ot("  tst r0,r0\n");
  ot("  moveq r0,#0x28\n");
  ot("  bleq Exception\n");
#else
  ot("  mov r0,#0x28\n");
  ot("  bl Exception\n");
#endif
  Cycles=4;
  OpEnd();

  ot("Op__fl%s ;@ Unrecognised f-line opcode\n", ms?"":":");
  ot("  sub r4,r4,#2\n");
#if USE_AFLINE_CALLBACK
  ot("  str r4,[r7,#0x40] ;@ Save PC\n");
  ot("  mov r1,r9,lsr #28\n");
  ot("  strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n");
  ot("  str r5,[r7,#0x5c] ;@ Save Cycles\n");
  ot("  ldr r11,[r7,#0x94] ;@ UnrecognizedCallback\n");
  ot("  tst r11,r11\n");
  ot("  movne lr,pc\n");
  ot("  movne pc,r11 ;@ call UnrecognizedCallback if it is defined\n");
  ot("  ldr r5,[r7,#0x5c] ;@ Load Cycles\n");
  ot("  ldrb r9,[r7,#0x46] ;@ r9 = Load Flags (NZCV)\n");
  ot("  mov r9,r9,lsl #28\n");
  ot("  ldr r4,[r7,#0x40] ;@ Load PC\n");
  ot("  tst r0,r0\n");
  ot("  moveq r0,#0x2c\n");
  ot("  bleq Exception\n");
#else
  ot("  mov r0,#0x2c\n");
  ot("  bl Exception\n");
#endif
  Cycles=4;
  OpEnd();


  for (op=0;op<0x10000;op++)
  {
    if ((op&0xfff)==0) { printf("%x",op>>12); fflush(stdout); } // Update progress

    OpAny(op);
  }

  ot("\n");

  printf("]\n");
}

// helper
static void ott(char *str, int par, char *nl, int nlp, int counter, int size)
{
  switch(size) {
    case 0: if((counter&7)==0) ot(ms?"  dcb ":"  .byte ");  break;
    case 1: if((counter&7)==0) ot(ms?"  dcw ":"  .hword "); break;
    case 2: if((counter&7)==0) ot(ms?"  dcd ":"  .long ");  break;
  }
  ot(str, par);
  if((counter&7)==7) ot(nl,nlp); else ot(",");
}

static void PrintJumpTable()
{
  int i=0,op=0,len=0;

  ot(";@ -------------------------- Jump Table --------------------------\n");

#if COMPRESS_JUMPTABLE
    int handlers=0,reps=0,*indexes,ip,u,out;
    // use some weird compression on the jump table
	indexes=(int *)malloc(0x10000*4);
	if(!indexes) { printf("ERROR: out of memory\n"); exit(1); }
	len=0x10000;

	// space for decompressed table
	ot(ms?"  area |.data|, data\n":"  .data\n  .align 4\n\n");

	ot("JumpTab%s\n", ms?"":":");
	if(ms) {
	  for(i = 0; i < 0xa000/8; i++)
	    ot("  dcd 0,0,0,0,0,0,0,0\n");
	} else
	  ot("  .rept 0x%x\n  .long 0,0,0,0,0,0,0,0\n  .endr\n", 0xa000/8);

    // hanlers live in "a-line" part of the table
	// first output nop,a-line,f-line handlers
	ot(ms?"  dcd Op____,Op__al,Op__fl,":"  .long Op____,Op__al,Op__fl,");
	handlers=3;

	for(i=0;i<len;i++)
    {
      op=CyJump[i];

	  for(u=i-1; u>=0; u--) if(op == CyJump[u]) break; // already done with this op?
	  if(u==-1 && op >= 0) {
		ott("Op%.4x",op," ;@ %.4x\n",i,handlers,2);
		indexes[op] = handlers;
	    handlers++;
      }
	}
	if(handlers&7) {
	  fseek(AsmFile, -1, SEEK_CUR); // remove last comma
	  for(i = 8-(handlers&7); i > 0; i--)
	    ot(",000000");
	  ot("\n");
	}
	if(ms) {
	  for(i = (0x4000-handlers)/8; i > 0; i--)
	    ot("  dcd 0,0,0,0,0,0,0,0\n");
	} else {
	  ot(ms?"":"  .rept 0x%x\n  .long 0,0,0,0,0,0,0,0\n  .endr\n", (0x4000-handlers)/8);
	}
    printf("total distinct hanlers: %i\n",handlers);
	// output data
	for(i=0,ip=0; i < 0xf000; i++, ip++) {
      op=CyJump[i];
	  if(op == -2) {
	    // it must skip a-line area, because we keep our data there
	    ott("0x%.4x", handlers<<4, "\n",0,ip++,1);
	    ott("0x%.4x", 0x1000, "\n",0,ip,1);
		i+=0xfff;
	    continue;
	  }
	  for(reps=1; i < 0xf000; i++, reps++) if(op != CyJump[i+1]) break;
	  if(op>=0) out=indexes[op]<<4; else out=0; // unrecognised
	  if(reps <= 0xe || reps==0x10) {
	    if(reps!=0x10) out|=reps; else out|=0xf; // 0xf means 0x10 (0xf appeared to be unused anyway)
	    ott("0x%.4x", out, "\n",0,ip,1);
      } else {
	    ott("0x%.4x", out, "\n",0,ip++,1);
	    ott("0x%.4x", reps,"\n",0,ip,1);
	  }
    }
	if(ip&1) ott("0x%.4x", 0, "\n",0,ip++,1);
	if(ip&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma
	ot("\n");
	if(ip&7) {
	  for(i = 8-(ip&7); i > 0; i--)
	    ot(",0x0000");
	  ot("\n");
	}
	if(ms) {
	  for(i = (0x2000-ip/2)/8; i > 0; i--)
	    ot("  dcd 0,0,0,0,0,0,0,0\n");
	} else {
	  ot("  .rept 0x%x\n  .long 0,0,0,0,0,0,0,0\n  .endr\n", (0x2000-ip/2)/8);
	}
	ot("\n");
	free(indexes);
#else
	ot("JumpTab%s\n", ms?"":":");
    len=0xfffe; // Hmmm, armasm 2.50.8684 messes up with a 0x10000 long jump table
                // notaz: same thing with GNU as 2.9-psion-98r2 (reloc overflow)
                // this is due to COFF objects using only 2 bytes for reloc count

    for (i=0;i<len;i++)
    {
      op=CyJump[i];
    
           if(op>=0)  ott("Op%.4x",op," ;@ %.4x\n",i-7,i,2);
      else if(op==-2) ott("Op__al",0, " ;@ %.4x\n",i-7,i,2);
      else if(op==-3) ott("Op__fl",0, " ;@ %.4x\n",i-7,i,2);
      else            ott("Op____",0, " ;@ %.4x\n",i-7,i,2);
    }
	if(i&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma

    ot("\n");
    ot(";@ notaz: we don't want to crash if we run into those 2 missing opcodes\n");
    ot(";@ so we leave this pattern to patch it later\n");
    ot("%s 0x78563412\n", ms?"  dcd":"  .long");
    ot("%s 0x56341290\n", ms?"  dcd":"  .long");
#endif
}

static int CycloneMake()
{
  int i;
  char *name="cyclone.s";
  
  // Open the assembly file
  if (ms) name="Cyclone.asm";
  AsmFile=fopen(name,"wt"); if (AsmFile==NULL) return 1;
  
  printf("Making %s...\n",name);

  ot("\n;@ Dave's Cyclone 68000 Emulator v%x.%.3x - Assembler Output\n\n",CycloneVer>>12,CycloneVer&0xfff);

  ot(";@ (c) Copyright 2003 Dave, All rights reserved.\n");
  ot(";@ some code (c) Copyright 2005-2006 notaz, All rights reserved.\n");
  ot(";@ Cyclone 68000 is free for non-commercial use.\n\n");
  ot(";@ For commercial use, separate licencing terms must be obtained.\n\n");

  CyJump=(int *)malloc(0x40000); if (CyJump==NULL) return 1;
  memset(CyJump,0xff,0x40000); // Init to -1
  for(i=0xa000; i<0xb000;  i++) CyJump[i] = -2; // a-line emulation
  for(i=0xf000; i<0x10000; i++) CyJump[i] = -3; // f-line emulation

  if (ms)
  {
    ot("  area |.text|, code\n");
    ot("  export CycloneInit\n");
    ot("  export CycloneRun\n");
    ot("  export CycloneSetSr\n");
    ot("  export CycloneGetSr\n");
    ot("  export CycloneVer\n");
    ot("\n");
    ot("CycloneVer dcd 0x%.4x\n",CycloneVer);
  }
  else
  {
    ot("  .global CycloneInit\n");
    ot("  .global CycloneRun\n");
    ot("  .global CycloneSetSr\n");
    ot("  .global CycloneGetSr\n");
    ot("  .global CycloneVer\n");
    ot("CycloneVer: .long 0x%.4x\n",CycloneVer);
  }
  ot("\n");

  PrintFramework();
  PrintOpcodes();
  PrintJumpTable();

  if (ms) ot("  END\n");

  fclose(AsmFile); AsmFile=NULL;

  printf("Assembling...\n");
  // Assemble the file
  if (ms) system("armasm Cyclone.asm");
  else    system("as -o Cyclone.o Cyclone.s");
  printf("Done!\n\n");

  free(CyJump);
  return 0;
}

int main()
{
  printf("\n  Dave's Cyclone 68000 Emulator v%x.%.3x - Core Creator\n\n",CycloneVer>>12,CycloneVer&0xfff);

  // Make GAS or ARMASM version
  CycloneMake();
  return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?