Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdint.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <pthread.h>
- typedef struct {
- uint32_t base;
- uint32_t element;
- void** labels;
- } pv_block_t;
- typedef struct {
- //Platform specific
- uint32_t a0,a1,a2,ra;
- //Emulation specific:
- bool delay;
- uint32_t delayPc;
- } pv_allegrexContext_t;
- typedef struct {
- int blockCount;
- pv_block_t* blocks;
- uint32_t compileAddress;
- void* platformContext;
- } pv_context_t;
- typedef struct {
- pthread_t posixThread;
- pv_context_t* context;
- void* userData;
- } pv_thread_t;
- #define PV_INSTRUCTION(address, code) label ## address: \
- ctx->compileAddress = address; \
- code
- #define PV_CODE(context,code) { \
- pv_context_t* ctx = context; \
- code \
- }
- #define PV_JUMP(address) { \
- printf("Jumping to 0x%08X\n",address); \
- pv_block_t* block = pv_findBlock(ctx,address); \
- goto *(block->labels[(address-block->base)/block->element]); \
- }
- #define ALLEGREX(code,del) { \
- pv_allegrexContext_t* ctx_p = (pv_allegrexContext_t*)ctx->platformContext; \
- code \
- if (ctx_p->delay) { \
- ctx_p->delay = del; /*most likely false - maybe even requirement?*/ \
- PV_JUMP(ctx_p->delayPc) \
- } ctx_p->delay = del; \
- }
- #define allegrexAdd_RRI(a,b,c) ALLEGREX(printf("Increasing something!\n"); ctx_p->a = ctx_p->b + c;,false)
- #define allegrexJ_I(a) ALLEGREX(ctx_p->delayPc = a;,true)
- #define allegrexJl_I(a) ALLEGREX(ctx_p->ra = ctx->compileAddress+8; allegrexJ_I(a),true)
- #define allegrexJr_R(a) ALLEGREX(allegrexJ_I(ctx_p->a),true)
- #define allegrexNop_(a) ALLEGREX(/*nothing*/,false)
- typedef void(pv_threadFunction_t)(pv_thread_t*);
- void pv_joinThread(pv_thread_t* thread) {
- pthread_join(thread->posixThread, NULL);
- }
- typedef struct {
- pv_threadFunction_t* function;
- pv_thread_t* thread;
- } _pv_posixData_t;
- void* _pv_posixThread(void* data) {
- _pv_posixData_t* threadData = (_pv_posixData_t*)data;
- threadData->function(threadData->thread);
- free(data);
- return NULL;
- }
- pv_thread_t* pv_createThread(pv_threadFunction_t* function, pv_context_t* context, void* userData) {
- pv_thread_t* thread = (pv_thread_t*)malloc(sizeof(pv_thread_t));
- _pv_posixData_t* threadData = (_pv_posixData_t*)malloc(sizeof(_pv_posixData_t));
- threadData->function = function;
- threadData->thread = thread;
- int result = pthread_create(&thread->posixThread, NULL, _pv_posixThread, (void*)threadData);
- thread->context = context;
- thread->userData = userData;
- return thread;
- }
- pv_block_t* pv_findBlock(pv_context_t* context, uint32_t address) {
- //TODO: Binary search or something like that would be neat. But useless for the current amount of blocks
- int i = context->blockCount;
- while(true) {
- pv_block_t* block = (pv_block_t*)&context->blocks[--i];
- if (address >= block->base) {
- return block;
- }
- }
- }
- pv_context_t* pv_CreateContextForAllegrex(void) {
- pv_context_t* context = (pv_context_t*)malloc(sizeof(pv_context_t));
- pv_allegrexContext_t* allegrexContext = (pv_allegrexContext_t*)malloc(sizeof(pv_allegrexContext_t));
- context->platformContext = allegrexContext;
- return context;
- }
- void entryCode(pv_thread_t* thread) {
- pv_context_t* context = thread->context;
- static const void* block0x00000000[] = {
- &&label0x00000000, &&label0x00000004, &&label0x00000008, &&label0x0000000C, &&label0x00000010,
- };
- static const void* block0x00000028[] = {
- &&label0x00000028, &&label0x0000002C,
- };
- static const pv_block_t blocks[] = {
- { 0x00000000, 4, (void**)block0x00000000 },
- { 0x00000028, 4, (void**)block0x00000028 },
- };
- context->blockCount = sizeof(blocks)/sizeof(pv_block_t);
- context->blocks = (pv_block_t*)blocks;
- PV_CODE(thread->context,
- PV_INSTRUCTION(0x00000000, allegrexAdd_RRI(a2,a2,1);)
- PV_INSTRUCTION(0x00000004, allegrexJl_I(0x00000028);)
- PV_INSTRUCTION(0x00000008, printf("delay slot!\n");
- allegrexAdd_RRI(a1,a1,1);)
- PV_INSTRUCTION(0x0000000C, printf("wb!\n");
- allegrexJr_R(a0);)
- PV_INSTRUCTION(0x00000010, allegrexNop_();)
- // 8 byte gap
- PV_INSTRUCTION(0x00000028, printf("Woo!\n");
- allegrexJr_R(ra);)
- PV_INSTRUCTION(0x0000002C, allegrexNop_();)
- )
- }
- int main(int argc, char* argv[]) {
- pv_context_t* entryContext = pv_CreateContextForAllegrex();
- pv_thread_t* entryThread = pv_createThread(entryCode,entryContext,NULL);
- pv_joinThread(entryThread);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement