📄 make6502.c
字号:
fprintf(fp, " jmp dword [%sregular+edx*4]\n\n", cpubasename);}ReadMemoryByte(UINT8 *pszTargetReg, UINT8 *pszAddress){ fprintf(fp, " mov edi, [_%sMemRead] ; Point to the read array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je short memoryRead%ld\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb short nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe short callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); assert(strcmp(pszAddress, "dx") == 0); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); if (strcmp(pszTargetReg, "bl") != 0) fprintf(fp, " mov bl, [_%sx] ; Get X back\n", cpubasename); if (strcmp(pszTargetReg, "cl") != 0) fprintf(fp, " mov cl, [_%sy] ; Get Y back\n", cpubasename); if (strcmp(pszTargetReg, "al") != 0) { fprintf(fp, " mov %s, al ; Get our value\n", pszTargetReg); fprintf(fp, " mov ax, [_%saf] ; Get our flags & stuff back\n", cpubasename); } else fprintf(fp, " mov ah, [_%saf + 1] ; Get our flags back\n", cpubasename); fprintf(fp, " jmp short readExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%ld:\n", dwGlobalLabel); if (bBankswitch) { fprintf(fp, " mov ebp, e%s ; Save our original address in EBP\n", pszAddress); fprintf(fp, " and ebp, 0ffffh ; Mask off the upper bits\n"); fprintf(fp, " mov edi, ebp ; Get our address\n"); fprintf(fp, " shr edi, %ld ; Find which bank we belong to\n", dwBankSize); fprintf(fp, " mov edi, [_%spbBankSwitch+edi*4] ; Get our base address for this bank\n", cpubasename); fprintf(fp, " or edi, edi ; NULL?\n"); fprintf(fp, " jz regularRead%ld ; If so, we're not banking!\n", dwGlobalLabel); // This is the code that fetches the data from the proper address fprintf(fp, " and ebp, 0%.4xh ; Mask out the unimportant stuff\n", (1 << dwBankSize) - 1); fprintf(fp, " mov %s, [ebp+edi] ; Get our banked data\n", pszTargetReg); fprintf(fp, " mov ebp, [_%sBase] ; Get our base pointer back\n", cpubasename); fprintf(fp, " jmp short readExit%ld\n", dwGlobalLabel); fprintf(fp, "regularRead%ld:\n", dwGlobalLabel); fprintf(fp, " mov ebp, [_%sBase] ; Get our base pointer back\n", cpubasename); } fprintf(fp, " mov %s, [ebp + e%s] ; Get our data\n\n", pszTargetReg, pszAddress); fprintf(fp, "readExit%ld:\n", dwGlobalLabel); dwGlobalLabel++;}ReadMemoryWord(){ fprintf(fp, " push edx ; Save address\n"); fprintf(fp, " mov [_%saf], ax ; Store AF\n", cpubasename); ReadMemoryByte("al", "dx"); fprintf(fp, " pop edx ; Restore address\n"); fprintf(fp, " inc dx ; Next address\n"); fprintf(fp, " push eax ; Save it for later\n"); fprintf(fp, " mov ax, [_%saf] ; Restore AF because it gets used later\n", cpubasename); ReadMemoryByte("dh", "dx"); fprintf(fp, " pop eax ; Restore it!\n"); fprintf(fp, " mov dl, al ; Restore our word into DX\n"); fprintf(fp, " mov ax, [_%saf] ; Restore AF\n", cpubasename);}WriteMemoryByte(UINT8 *pszSourceReg, UINT8 *pszAddress){ fprintf(fp, " mov edi, [_%sMemWrite] ; Point to the write array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je near memoryWrite%ld ; Yes - go write it!\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes... go to the next addr\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); // Save off our registers! fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " mov [_%saf], ax ; Save Accumulator & flags\n", cpubasename); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_%spc], si ; Save our program counter\n", cpubasename); if (bUseStack) { fprintf(fp, " push edi ; Pointer to MemoryWriteByte structure\n"); if (strcmp(pszSourceReg, "bl") == 0) fprintf(fp, " push ebx ; The byte value\n"); if (strcmp(pszSourceReg, "bh") == 0) { fprintf(fp, " mov bl, bh ; Put a copy here\n"); fprintf(fp, " push ebx ; The byte value\n"); } if (strcmp(pszSourceReg, "cl") == 0) fprintf(fp, " push ecx ; The byte value\n"); if (strcmp(pszSourceReg, "al") == 0) fprintf(fp, " push eax ; The byte value\n"); fprintf(fp, " and e%s, 0ffffh ; Only lower 16 bits\n", pszAddress); fprintf(fp, " push e%s ; The address\n", pszAddress); } else // Register calling convention { if ((strcmp(pszSourceReg, "al") == 0) && (strcmp(pszAddress, "dx") == 0)) fprintf(fp, " xchg eax, edx ; Swap 'em\n"); else { if (strcmp(pszAddress, "bx") == 0) fprintf(fp, " mov eax, ebx ; Address\n"); if (strcmp(pszAddress, "cx") == 0) fprintf(fp, " mov eax, ebx ; Address\n"); if (strcmp(pszAddress, "dx") == 0) fprintf(fp, " mov eax, edx ; Address\n"); if (strcmp(pszSourceReg, "bh") == 0) { fprintf(fp, " mov bl, bh ; Put a copy here\n"); fprintf(fp, " mov edx, ebx ; The byte value\n"); } if (strcmp(pszSourceReg, "bl") == 0) fprintf(fp, " mov edx, ebx ; The byte value\n"); if (strcmp(pszSourceReg, "cl") == 0) fprintf(fp, " mov edx, ecx ; The byte value\n"); if (strcmp(pszSourceReg, "al") == 0) fprintf(fp, " mov edx, eax ; The byte value\n"); } fprintf(fp, " mov ebx, edi ; MemoryWriteByte structure\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); if (bUseStack) fprintf(fp, " add esp, 12 ; Get rid of our stack\n"); fprintf(fp, " xor ebx, ebx ; Zero this\n"); fprintf(fp, " xor ecx, ecx ; This too!\n"); fprintf(fp, " mov bl, [_%sx] ; Get X back\n", cpubasename); fprintf(fp, " mov cl, [_%sy] ; Get Y back\n", cpubasename); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_%sBase] ; Base pointer comes back\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov ax, [_%saf] ; Get our flags & stuff back\n", cpubasename); fprintf(fp, " jmp short writeMacroExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryWrite%ld:\n", dwGlobalLabel); fprintf(fp, " mov [ebp + e%s], %s ; Store the byte\n\n", pszAddress, pszSourceReg); fprintf(fp, "writeMacroExit%ld:\n", dwGlobalLabel); ++dwGlobalLabel;}void ReadMemoryByteHandler(){ Alignment(); fprintf(fp, "; This is a generic read memory byte handler when a foreign\n"); fprintf(fp, "; handler is to be called\n\n"); fprintf(fp, "ReadMemoryByte:\n"); fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " mov [_%saf], ax ; Save Accumulator & flags\n", cpubasename); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_%spc], si ; Save our program counter\n", cpubasename); if (bUseStack) { fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " and edx, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " push edx ; And our desired address\n"); } else { fprintf(fp, " mov eax, edx ; Get our desired address reg\n"); fprintf(fp, " mov edx, edi ; Pointer to the structure\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); if (bUseStack) fprintf(fp, " add esp, 8 ; Get the junk off the stack\n"); fprintf(fp, " xor ebx, ebx ; Zero X\n"); fprintf(fp, " xor ecx, ecx ; Zero Y\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_%sBase] ; Base pointer comes back\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); ++dwGlobalLabel;}FetchInstructionWord(){ fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Increment past instruction\n");}Absolute(){ FetchInstructionWord();}ZeroPage(){ FetchInstructionByte();}ZeroPageX(){ FetchInstructionByte(); fprintf(fp, " add dl, bl ; Add X\n");}ZeroPageY(){ FetchInstructionByte(); fprintf(fp, " add dl, cl ; Add Y\n");}AbsoluteX(){ FetchInstructionWord(); fprintf(fp, " add dx, bx ; Add X\n");}AbsoluteY(){ FetchInstructionWord(); fprintf(fp, " add dx, cx ; Add Y\n");}IndirectX(){ FetchInstructionByte(); fprintf(fp, " add dl, bl ; Add in X\n"); if (bZeroDirect) fprintf(fp, " mov dx, [ebp+edx] ; Get our 16 bit address\n"); else ReadMemoryWord();}IndirectY(){ FetchInstructionByte(); if (bZeroDirect) fprintf(fp, " mov dx, [ebp+edx] ; Get our 16 bit address\n"); else ReadMemoryWord(); fprintf(fp, " add dx, cx ; Add in Y\n");}DataSegment(){ UINT32 dwLoop = 0; UINT32 dwBit = 0; UINT8 bValue = 0; fprintf(fp, " section .data\n"); Alignment(); if (bPlain) fprintf(fp, " global %spc\n\n",cpubasename); else fprintf(fp, " global _%spc\n\n",cpubasename); fprintf(fp, " global %spbBankSwitch_, _%spbBankSwitch\n\n", cpubasename, cpubasename); fprintf(fp, "_%scontextBegin:\n", cpubasename); fprintf(fp, "\n"); fprintf(fp, "; DO NOT CHANGE THE ORDER OF THE FOLLOWING REGISTERS!\n"); fprintf(fp, "\n"); fprintf(fp, "_%sBase dd 0 ; Base address for 6502 stuff\n", cpubasename); fprintf(fp, "_%sMemRead dd 0 ; Offset of memory read structure array\n", cpubasename); fprintf(fp, "_%sMemWrite dd 0 ; Offset of memory write structure array\n", cpubasename); if (bBankswitch) { fprintf(fp, "_%spbBankSwitch:\n", cpubasename); for (dwLoop = 0; dwLoop < 32; dwLoop++) { if (dwLoop * (1 << dwBankSize) < 65536) fprintf(fp, " dd 0 ; Addr=$%.4x\n", dwLoop * (1 << dwBankSize)); else fprintf(fp, " dd 0 ; Filler\n"); } } fprintf(fp, "_%saf dw 0 ; A register and flags\n", cpubasename); fprintf(fp, "_%spc:\n", cpubasename); fprintf(fp, "%spc dw 0 ; 6502 Program counter\n", cpubasename); fprintf(fp, "_%sx db 0 ; X\n", cpubasename); fprintf(fp, "_%sy db 0 ; Y\n", cpubasename); fprintf(fp, "_%ss db 0 ; s\n", cpubasename); fprintf(fp, "_irqPending db 0 ; Non-zero if an IRQ is pending\n"); fprintf(fp, "\n"); fprintf(fp, "_%scontextEnd:\n", cpubasename); if (bBankswitch) { fprintf(fp, "_%sBaseAddr dd 0 ; Temporary base address\n", cpubasename); fprintf(fp, "_%sBasePage dd 0 ; What page are we on? (ready for use)\n", cpubasename); } fprintf(fp, "\n"); Alignment(); fprintf(fp, "_tempAddr dd 0 ; Temporary address storage\n"); fprintf(fp, "dwElapsedTicks dd 0 ; Elapsed ticks!\n"); fprintf(fp, "cyclesRemaining dd 0 ; # Of cycles remaining\n"); fprintf(fp, "_altFlags db 0 ; Storage for I, D, and B\n"); // Now we write out our tables Alignment(); for (dwLoop = 0; dwLoop < 256; dwLoop++) bUsed[dwLoop] = 0; // Create flag translation tables fprintf(fp, "bit6502tox86:\n"); for (dwLoop = 0; dwLoop < 256; dwLoop++) { bValue = 0; for (dwBit = 0; dwBit < 8; dwBit++) { if (bBit6502tox86[dwBit] != 0xff) { if ((1 << dwBit) & dwLoop) bValue |= (1 << bBit6502tox86[dwBit]); } } if ((dwLoop & 0x0f) == 0) fprintf(fp, " db "); if (bValue < 0xa0) fprintf(fp, "%.2xh", bValue); else fprintf(fp, "0%.2xh", bValue); if ((dwLoop & 0x0f) != 0xf) fprintf(fp, ", "); else fprintf(fp, "\n"); } // Create flag translation tables fprintf(fp, "\nbitx86to6502:\n"); for (dwLoop = 0; dwLoop < 256; dwLoop++) { bValue = 0; for (dwBit = 0; dwBit < 8; dwBit++) { if (bBitx86to6502[dwBit] != 0xff) { if ((1 << dwBit) & dwLoop) bValue |= (1 << bBitx86to6502[dwBit]); } } if ((dwLoop & 0x0f) == 0) fprintf(fp, " db "); if (bValue < 0xa0) fprintf(fp, "%.2xh", bValue); else fprintf(fp, "0%.2xh", bValue); if ((dwLoop & 0x0f) != 0xf) fprintf(fp, ", "); else fprintf(fp, "\n"); } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used dwLoop = 0; while (StandardOps[dwLoop].Emitter) { assert(StandardOps[dwLoop].bOpCode < 0x100); if (bUsed[StandardOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops! %.2x\n", StandardOps[dwLoop].bOpCode); exit(1); } if (b6510Instructions) bUsed[StandardOps[dwLoop].bOpCode] = 1; else { if (StandardOps[dwLoop].b6510Instruction == FALSE) bUsed[StandardOps[dwLoop].bOpCode] = 1; } dwLoop++; } fprintf(stderr, "%ld Unique opcodes\n", dwLoop); // Now that that's taken care of, emit the table fprintf(fp, "%sregular:\n", cpubasename); dwLoop = 0; while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "RegInst%.2x", dwLoop); else { if (bInvalidAsNop) fprintf(fp, "RegInstea"); else fprintf(fp, "invalidInsByte"); } fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n");}CodeSegmentBegin(){ fprintf(fp, " section .text\n");}CodeSegmentEnd(){}ProgramEnd(){ fprintf(fp, " end\n");}EmitRegularInstructions(){ UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; while (dwLoop < 0x100) { dwLoop2 = 0; while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffff) dwLoop2++; assert(dwLoop2 < 0x100); if (StandardOps[dwLoop2].Emitter && StandardOps[dwLoop2].bOpCode != 0xffff && bUsed[dwLoop]) StandardOps[dwLoop2].Emitter((UINT16) dwLoop); dwLoop++; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -