2023-10-18 22:52:24 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
2023-10-19 00:27:10 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/mman.h>
|
2023-10-18 22:52:24 +00:00
|
|
|
|
2023-10-18 23:45:03 +00:00
|
|
|
// A -> D0
|
|
|
|
// BC -> D1
|
|
|
|
// DE -> D2
|
|
|
|
// HL -> A0
|
|
|
|
// SP -> A7
|
2023-10-18 22:52:24 +00:00
|
|
|
|
|
|
|
uint8_t out_code[1024];
|
|
|
|
uint8_t memory[1024]; // ???
|
|
|
|
uint32_t out_ptr;
|
|
|
|
|
|
|
|
struct basic_block {
|
|
|
|
// in 68k space?
|
2023-10-18 23:45:03 +00:00
|
|
|
uint8_t code[256];
|
2023-10-18 22:52:24 +00:00
|
|
|
size_t length;
|
|
|
|
};
|
|
|
|
|
|
|
|
// need some kind of map from gb address to struct basic_block?
|
|
|
|
|
|
|
|
uint8_t test_code[] = {
|
2023-10-18 23:45:03 +00:00
|
|
|
0x00, // nop
|
2023-10-18 23:48:01 +00:00
|
|
|
0x06, 0x00, // ld b, $0
|
|
|
|
0x0e, 0x11, // ld c, $11
|
|
|
|
0x16, 0x22, // ld d, $22
|
|
|
|
0x1e, 0x33, // ld e, $33
|
|
|
|
0x26, 0x44, // ld h, $44
|
|
|
|
0x2e, 0x55, // ld l, $55
|
|
|
|
0x36, 0x66, // ld [hl], $66
|
|
|
|
0x3e, 0x77, // ld a, $77
|
|
|
|
0x01, 0x23, 0x01, // ld bc, $0123
|
|
|
|
0x11, 0x67, 0x45, // ld de, $4567
|
|
|
|
0x21, 0xab, 0x89, // ld hl, $89ab
|
|
|
|
0x31, 0xef, 0xcd, // ld sp, $cdef
|
|
|
|
0x3e, 0x0a, // .loop: ld a, 10
|
|
|
|
0x3d, // dec a
|
|
|
|
0x20, 0xfd, // jr nz, .loop
|
2023-10-18 23:45:03 +00:00
|
|
|
0x18, 0xfe, // jr $-1
|
|
|
|
0xc9 // ret
|
2023-10-18 22:52:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct basic_block *compile_block(uint16_t src_address, uint8_t *gb_code)
|
|
|
|
{
|
2023-10-18 23:45:03 +00:00
|
|
|
uint8_t instruction;
|
2023-10-18 22:52:24 +00:00
|
|
|
struct basic_block *bblock;
|
2023-10-18 23:45:03 +00:00
|
|
|
uint32_t dst_ptr = 0;
|
|
|
|
uint16_t src_ptr = 0;
|
2023-10-19 00:27:10 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
printf("compile block starting at 0x%04x\n", src_address);
|
2023-10-18 22:52:24 +00:00
|
|
|
|
|
|
|
bblock = malloc(sizeof *bblock);
|
2023-10-19 00:27:10 +00:00
|
|
|
|
|
|
|
// for testing...
|
|
|
|
ret = mprotect(
|
|
|
|
(void *) ((uint64_t) bblock & 0xfffffffffffff000L),
|
|
|
|
4096,
|
|
|
|
PROT_READ | PROT_WRITE | PROT_EXEC
|
|
|
|
);
|
|
|
|
if (ret == -1) {
|
|
|
|
perror("mprotect");
|
|
|
|
exit(0);
|
|
|
|
}
|
2023-10-18 23:45:03 +00:00
|
|
|
// bblock->code = out_code + start;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
instruction = gb_code[src_ptr++];
|
2023-10-19 00:27:10 +00:00
|
|
|
if (instruction == 0xfd) {
|
|
|
|
// invalid opcode for testing
|
|
|
|
break;
|
|
|
|
}
|
2023-10-18 23:45:03 +00:00
|
|
|
}
|
2023-10-18 22:52:24 +00:00
|
|
|
|
2023-10-19 00:27:10 +00:00
|
|
|
bblock->length = 6;
|
|
|
|
bblock->code[0] = 0xb8; // mov eax, 1234h
|
|
|
|
bblock->code[1] = 0x34;
|
|
|
|
bblock->code[2] = 0x12;
|
|
|
|
bblock->code[3] = 0x00;
|
|
|
|
bblock->code[4] = 0x00;
|
|
|
|
bblock->code[5] = 0xc3; // ret
|
|
|
|
|
2023-10-18 22:52:24 +00:00
|
|
|
return bblock;
|
|
|
|
}
|
|
|
|
|
|
|
|
void run_block(struct basic_block *bblock)
|
|
|
|
{
|
|
|
|
// calling convention? do i need to do this from asm?
|
2023-10-18 23:45:03 +00:00
|
|
|
uint16_t jump_target = ((uint16_t (*)()) bblock->code)();
|
2023-10-18 22:52:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO
|
2023-10-19 00:27:10 +00:00
|
|
|
void block_cache_add(uint16_t src_address, struct basic_block *bblock)
|
|
|
|
{
|
|
|
|
// no-op
|
|
|
|
}
|
|
|
|
|
|
|
|
struct basic_block *block_cache_get(uint16_t src_address)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2023-10-18 22:52:24 +00:00
|
|
|
|
|
|
|
// 1. compile each block ending in a jump
|
|
|
|
// 2. turn the jump into a return
|
|
|
|
// 3. add the compiled code to some kind of cache
|
|
|
|
// 3. return back to check the cache and maybe compile the next block
|
|
|
|
|
2023-10-19 00:27:10 +00:00
|
|
|
void run_all(uint8_t *gb_code)
|
2023-10-18 22:52:24 +00:00
|
|
|
{
|
|
|
|
struct basic_block *bblock;
|
2023-10-19 00:27:10 +00:00
|
|
|
uint16_t jump_target = 0;
|
2023-10-18 22:52:24 +00:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
bblock = block_cache_get(jump_target);
|
|
|
|
if (!bblock) {
|
2023-10-19 00:27:10 +00:00
|
|
|
bblock = compile_block(jump_target, gb_code + jump_target);
|
|
|
|
if (bblock->length == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
block_cache_add(jump_target, bblock);
|
2023-10-18 22:52:24 +00:00
|
|
|
}
|
2023-10-19 00:27:10 +00:00
|
|
|
|
|
|
|
jump_target = ((uint16_t (*)()) bblock->code)();
|
2023-10-18 22:52:24 +00:00
|
|
|
}
|
2023-10-19 00:27:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
long len;
|
|
|
|
uint8_t *data;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
data = test_code;
|
|
|
|
} else {
|
|
|
|
fp = fopen(argv[1], "r");
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
|
|
len = ftell(fp);
|
|
|
|
rewind(fp);
|
|
|
|
data = malloc(len);
|
|
|
|
fread(data, 1, len, fp);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
run_all(data);
|
|
|
|
|
|
|
|
if (data != test_code) {
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
2023-10-18 22:52:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|