mirror of
https://github.com/mlaux/gb6.git
synced 2026-10-24 16:02:16 +00:00
142 lines
5.2 KiB
C
142 lines
5.2 KiB
C
#ifndef COMPILER_H
|
|
#define COMPILER_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
// D0 = scratch/C interop return value
|
|
// D1 = scratch
|
|
// D2 = accumulated cycle count
|
|
// D3 = scratch/dispatcher return value (next GB PC)
|
|
// D4 = A (GB accumulator)
|
|
// D5 = BC (split: 0x00BB00CC)
|
|
// D6 = DE (split: 0x00DD00EE)
|
|
// D7 = flags (00000Z0C)
|
|
|
|
// A0 = scratch
|
|
// A1 = scratch
|
|
// A2 = HL (contiguous: 0xHHLL)
|
|
// A3 = SP
|
|
// A4 = runtime context pointer
|
|
// A5 = read page table base (dmg + 0x80)
|
|
// A6 = write page table base (dmg + 0x480)
|
|
// A7 = 68k stack pointer
|
|
|
|
#define REG_68K_D_SCRATCH_0 0
|
|
#define REG_68K_D_SCRATCH_1 1
|
|
#define REG_68K_D_CYCLE_COUNT 2
|
|
#define REG_68K_D_NEXT_PC 3
|
|
#define REG_68K_D_A 4
|
|
#define REG_68K_D_BC 5
|
|
#define REG_68K_D_DE 6
|
|
#define REG_68K_D_FLAGS 7
|
|
|
|
#define REG_68K_A_SCRATCH_1 0
|
|
#define REG_68K_A_SCRATCH_2 1
|
|
#define REG_68K_A_HL 2
|
|
#define REG_68K_A_SP 3
|
|
#define REG_68K_A_CTX 4
|
|
#define REG_68K_A_READ_PAGE 5
|
|
#define REG_68K_A_WRITE_PAGE 6
|
|
|
|
#define COND_HI 2 // unsigned higher
|
|
#define COND_CC 4 // carry clear (nc)
|
|
#define COND_CS 5 // carry set (c)
|
|
#define COND_NE 6 // not equal/not zero (nz)
|
|
#define COND_EQ 7 // equal/zero (z)
|
|
#define COND_NONE -1 // not a conditional branch
|
|
|
|
// Runtime context offsets
|
|
#define JIT_CTX_DMG 0
|
|
#define JIT_CTX_READ 4
|
|
#define JIT_CTX_WRITE 8
|
|
#define JIT_CTX_EI_DI 12
|
|
#define JIT_CTX_INTCHECK 16 // unused
|
|
#define JIT_CTX_ROM_BANK 17 // 1 byte (current ROM bank for MBC)
|
|
// 2 bytes padding to align to 4 bytes
|
|
#define JIT_CTX_BANK0_CACHE 20 // struct code_block **bank0_cache
|
|
#define JIT_CTX_BANKED_CACHE 24 // struct code_block ***banked_cache
|
|
#define JIT_CTX_UPPER_CACHE 28 // struct code_block **upper_cache
|
|
#define JIT_CTX_DISPATCH 32 // void *dispatcher_return
|
|
#define JIT_CTX_READ16 36 // u16 (*dmg_read16)(void *_dmg, u16 address);
|
|
#define JIT_CTX_WRITE16 40 // void (*dmg_write16)(void *_dmg, u16 address, u16 data);
|
|
#define JIT_CTX_CYCLES 44 // u32: accumulated GB cycles
|
|
#define JIT_CTX_PATCH_HELPER 48 // void *patch_helper routine
|
|
#define JIT_CTX_READ_CYCLES 52 // u32: GB cycles at dmg_read call
|
|
#define JIT_CTX_DAA_STATE 56 // 2 bytes: [0]=old_A, [1]=N flag (for DAA)
|
|
#define JIT_CTX_FRAME_CYCLES_PTR 60 // u32 *frame_cycles_ptr (dmg->frame_cycles)
|
|
#define JIT_CTX_STOP_FUNC 64 // void *stop_func (for STOP/speed switch)
|
|
#define JIT_CTX_EFF_DOUBLE_SPEED 68 // u8: 1 if double speed active AND not ignored
|
|
#define JIT_CTX_GB_SP 72 // u16: GB stack pointer value
|
|
#define JIT_CTX_STACK_IN_RAM 76 // non-zero if A3 points to native WRAM/HRAM
|
|
#define JIT_CTX_WAKE_LIMIT 80 // u32: CPU-cycle distance to the earliest
|
|
// deadline; dispatcher exit budget and the
|
|
// HALT/idle fast-forward target
|
|
// GB6_PROFILING only, written by the fast-forward paths
|
|
#define JIT_CTX_SKIPPED 84 // u32: GB cycles skipped by wake_skip
|
|
#define JIT_CTX_LY_SKIPS 88 // u32: LY-wait clamp skips (cycles unknown)
|
|
#define JIT_CTX_MBC_WRITE 92 // void *mbc_write_func (dmg_mbc_write)
|
|
|
|
struct code_block {
|
|
// number of bytes populated in code[]
|
|
size_t length;
|
|
// number of GB instructions
|
|
size_t count;
|
|
uint16_t src_address;
|
|
uint16_t end_address; // address after last instruction
|
|
|
|
// set when compilation hits unknown opcode
|
|
uint16_t error;
|
|
uint16_t failed_opcode;
|
|
uint16_t failed_address;
|
|
// at the end so arena can only be bumped by actual code size
|
|
uint8_t code[2048];
|
|
};
|
|
|
|
extern uint16_t m68k_offsets[256];
|
|
|
|
// deferred cycle counting: instruction cycles accumulate at compile time in
|
|
// pending_cycles and are materialized into D2 on exit
|
|
extern int pending_cycles;
|
|
void defer_cycles(int n);
|
|
void flush_cycles(struct code_block *block);
|
|
|
|
// GB offsets targeted by backward jumps in the current block (pre-scan)
|
|
extern uint8_t flush_at[256];
|
|
|
|
// SM83 instruction lengths (CB counted as 2)
|
|
extern const uint8_t insn_length[256];
|
|
|
|
typedef uint8_t (*dmg_read_fn)(void *dmg, uint16_t address);
|
|
|
|
// cache store function signature for registering mid-block entry points
|
|
typedef int (*cache_store_fn)(uint16_t pc, uint8_t bank, void *code_ptr);
|
|
|
|
// allocator function signature for arena allocation
|
|
typedef void *(*alloc_fn)(size_t size);
|
|
|
|
// compile-time context
|
|
struct compile_ctx {
|
|
void *dmg; // for memory reads
|
|
dmg_read_fn read;
|
|
cache_store_fn cache_store; // NULL in tests, registers mid-block entries
|
|
alloc_fn alloc; // NULL uses malloc, otherwise arena_alloc
|
|
uint8_t current_bank; // current ROM bank for cache_store calls
|
|
// GB memory the emitted fast paths address absolutely
|
|
void *wram_base; // dmg->wram
|
|
void *hram_base; // dmg->hram
|
|
void *joyp_ptr; // &dmg->joyp, the maintained FF00 shadow
|
|
uint16_t bank_reg_lo; // MBC ROM-bank select range for the
|
|
uint16_t bank_reg_hi; // same-bank write skip, both 0 = off
|
|
};
|
|
|
|
struct code_block *compile_block(uint16_t src_address, struct compile_ctx *ctx);
|
|
|
|
// Free a compiled block
|
|
void block_free(struct code_block *block);
|
|
|
|
void compile_join_bc(struct code_block *block, int dreg);
|
|
void compile_join_de(struct code_block *block, int dreg);
|
|
|
|
#endif
|