247 lines
4.9 KiB
C
247 lines
4.9 KiB
C
|
|
|
|
#include "ugl.h"
|
|
#include "ugl_bc.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
/* 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");
|
|
} |