#include "ugl.h" #include "ugl_bc.h" #include #include /* arrays & variables */ #define UGL_MAX_BYTECODE_LEN (63*1024) uint8_t ugl_bytecode_array[UGL_MAX_BYTECODE_LEN]; uint16_t ugl_bytecode_len; #define UGL_MAX_LABEL_CNT 128 char ugl_label_name[UGL_MAX_LABEL_CNT][UGL_MAX_IDENTIFIER_LEN+1]; uint16_t ugl_label_bytecode_pos[UGL_MAX_LABEL_CNT]; /* position in the bytecode array */ int ugl_label_cnt; /* procedures */ void ugl_AddBytecode(uint8_t x) { ugl_bytecode_array[ugl_bytecode_len] = x; ugl_bytecode_len++; } void ugl_InitBytecode(void) { ugl_bytecode_len = 0; ugl_AddBytecode(BC_CMD_RETURN_FROM_PROCEDURE); } /* extern uint8_t ugl_bytecode_array[]; void ugl_ExecBytecode(void) { bc_t bc; bc_exec(&bc, ugl_bytecode_array, 0); } */ void ugl_CheckForAllLabelsDefined(void) { int i; for( i = 0; i < ugl_label_cnt; i++ ) { if ( ugl_label_bytecode_pos[ugl_label_cnt] == 0x0ffff ) { ugl_err("undefined label '%s'", ugl_label_name[i] ); } } } void ugl_ResolveSymbols(void) { uint8_t *code = ugl_bytecode_array; uint8_t *dest = ugl_bytecode_array+ugl_bytecode_len; uint16_t val; uint8_t cmd; ugl_CheckForAllLabelsDefined(); ugl_glog("Resolve start=%p, end=%p", code, dest); ugl_glog("Resolve bytecode len=%d", ugl_bytecode_len); while( code < dest ) { cmd = *code; ugl_glog("Resolve pos=%p, cmd=%02x", code, cmd); code++; val = cmd; val &=0x0f0; /* put upper four bit as upper 4bit of the 12bit value into val */ val <<= 4; switch(cmd&15) { case BC_CMD_LOAD_12BIT: code++; break; case BC_CMD_CALL_BUILDIN: code++; break; case BC_CMD_CALL_BUILDIN_POP_STACK: code++; break; case BC_CMD_BRANCH: val |= *code; code++; ugl_glog("Resolve BRANCH '%s' (idx=%d)", ugl_label_name[val], val); val = ugl_GetLabelBytecodePos(val); val = (val - (uint16_t)(code - ugl_bytecode_array)); ugl_glog("Resolve BRANCH delta=0x%03x", val); *(code-2) &= 0x0f; *(code-2) |= (val >> 4) & 0x0f0; *(code-1) = val & 255; break; case BC_CMD_POP_ARG_STACK: break; case BC_CMD_PUSH_ARG_STACK: break; case BC_CMD_CALL_PROCEDURE: val = code[0]; val <<= 8; val |= code[1]; ugl_glog("Resolve CALL Procedre '%s' pos=%u", ugl_label_name[val], ugl_GetLabelBytecodePos(val)); val = ugl_GetLabelBytecodePos(val); *code = val>>8; code++; *code = val&255; code++; break; default: /* assume 0x0f, extended command */ switch( cmd ) { case BC_CMD_LOAD_0: break; case BC_CMD_LOAD_1: break; case BC_CMD_LOAD_16BIT: code++; code++; break; case BC_CMD_RETURN_FROM_PROCEDURE: break; case BC_CMD_JUMP_NOT_ZERO: case BC_CMD_JUMP_ZERO: val = code[0]; val <<= 8; val |= code[1]; ugl_glog("Resolve JUMP '%s'", ugl_label_name[val]); val = ugl_GetLabelBytecodePos(val); *code = val>>8; code++; *code = val&255; code++; break; #ifdef NOT_USED case BC_CMD_CALL_PROCEDURE: val = code[0]; val <<= 8; val |= code[1]; ugl_glog("Resolve CALL Procedre '%s' pos=%u", ugl_label_name[val], ugl_GetLabelBytecodePos(val)); val = ugl_GetLabelBytecodePos(val); *code = val>>8; code++; *code = val&255; code++; break; #endif /* case BC_CMD_POP_ARG_STACK: break; */ default: ugl_err("Resolve: Unexpected command"); break; } break; } /* switch() */ } /* while */ } static int ugl_FindLabel(const char *name) { int i; for( i = 0; i < ugl_label_cnt; i++ ) { if (strcmp(name, ugl_label_name[i] ) == 0 ) return i; } return -1; } static int ugl_AddLabel(const char *name) { strcpy(ugl_label_name[ugl_label_cnt], name); ugl_label_bytecode_pos[ugl_label_cnt] = 0x0ffff; ugl_label_cnt++; if ( ugl_label_cnt >= UGL_MAX_LABEL_CNT ) ugl_err("max number of labels reached, label=%s", name); return ugl_label_cnt-1; } int ugl_GetLabel(const char *name) { int idx; idx = ugl_FindLabel(name); if ( idx >= 0 ) return idx; return ugl_AddLabel(name); } void ugl_SetLabelBytecodePos(const char *name, uint16_t bytecode_pos) { int idx; idx = ugl_GetLabel(name); if ( ugl_label_bytecode_pos[idx] != 0x0ffff ) ugl_err("double definition of label '%s'", name); ugl_label_bytecode_pos[idx] = bytecode_pos; } uint16_t ugl_GetLabelBytecodePos(int idx) { if ( ugl_label_bytecode_pos[idx] == 0x0ffff ) ugl_err("undefined label '%s'", ugl_label_name[idx]); return ugl_label_bytecode_pos[idx]; } void ugl_WriteBytecodeCArray(FILE *fp, const char *name) { uint16_t i; fprintf(fp, "unsigned char %s[] =\n \"", name); i = 0; while ( i < ugl_bytecode_len ) { fprintf(fp, "\\x%02x", ugl_bytecode_array[i]); if ( i+1 == ugl_bytecode_len ) { break; } if ( (i & 0x0f) == 0x0f ) { fprintf(fp, "\"\n \""); } i++; } fprintf(fp, "\";\n\n"); }