mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-22 02:31:28 +00:00
Assembly statement parsing
This commit is contained in:
parent
d51718118a
commit
629f6f1e63
3 changed files with 77 additions and 11 deletions
73
asm.c
73
asm.c
|
@ -348,7 +348,9 @@ static GMQCC_INLINE bool asm_parse_func(const char *skip, size_t line, asm_state
|
|||
code_globals_add (code_chars_elements);
|
||||
code_chars_put (name, strlen(name));
|
||||
code_chars_add ('\0');
|
||||
|
||||
|
||||
/* update assembly state */
|
||||
*state = ASM_FUNCTION;
|
||||
util_debug("ASM", "added context function %s to function table\n", name);
|
||||
}
|
||||
|
||||
|
@ -359,6 +361,69 @@ static GMQCC_INLINE bool asm_parse_func(const char *skip, size_t line, asm_state
|
|||
return false;
|
||||
}
|
||||
|
||||
static GMQCC_INLINE bool asm_parse_stmt(const char *skip, size_t line, asm_state *state) {
|
||||
/*
|
||||
* This parses a valid statement in assembly and adds it to the code
|
||||
* table to be wrote. This needs to handle correct checking of all
|
||||
* statements to ensure the correct amount of operands are passed to
|
||||
* the menomic. This must also check for valid function calls (ensure
|
||||
* the names selected exist in the program scope) and ensure the correct
|
||||
* CALL* is used (depending on the amount of arguments the function
|
||||
* is expected to take)
|
||||
*/
|
||||
char *c = NULL;
|
||||
prog_section_statement s;
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
|
||||
/*
|
||||
* Iterate all possible instructions and check if the selected
|
||||
* instructure in the input stream `skip` is actually a valid
|
||||
* instruction.
|
||||
*/
|
||||
if (strstr(skip, asm_instr[i].m) == &skip[0]) {
|
||||
/*
|
||||
* Parse the operands for `i` (the instruction). The order
|
||||
* of asm_instr is in the order of the menomic encoding so
|
||||
* `i` == menomic encoding.
|
||||
*/
|
||||
s.opcode = i;
|
||||
switch (asm_instr[i].o) {
|
||||
/*
|
||||
* Each instruction can have from 0-3 operands; and can
|
||||
* be used with less or more operands depending on it's
|
||||
* selected use.
|
||||
*
|
||||
* DONE for example can use either 0 operands, or 1 (to
|
||||
* emulate the effect of RETURN)
|
||||
*/
|
||||
default:
|
||||
skip += asm_instr[i].l+1;
|
||||
/* skip whitespace */
|
||||
while (*skip == ' ' || *skip == '\t')
|
||||
skip++;
|
||||
/*
|
||||
* TODO: parse operands correctly figure out what it is
|
||||
* that the assembly is trying to do, i.e string table
|
||||
* lookup, function calls etc.
|
||||
*
|
||||
* This needs to have a fall state, we start from the
|
||||
* end of the string and work backwards.
|
||||
*/
|
||||
case '3':
|
||||
s.o3.s1 = 0;
|
||||
case '2':
|
||||
s.o2.s1 = 0;
|
||||
case '1':
|
||||
s.o1.s1 = 0;
|
||||
}
|
||||
/* add the statement now */
|
||||
code_statements_add(s);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void asm_parse(FILE *fp) {
|
||||
char *data = NULL;
|
||||
char *skip = NULL;
|
||||
|
@ -379,9 +444,11 @@ void asm_parse(FILE *fp) {
|
|||
skip = util_strrnl(copy); /* delete newline */
|
||||
|
||||
/* parse type */
|
||||
if(asm_parse_type(skip, line, &state)){ asm_end("asm_parse_type\n"); }
|
||||
if (asm_parse_type(skip, line, &state)) { asm_end("asm_parse_type\n"); }
|
||||
/* parse func */
|
||||
if(asm_parse_func(skip, line, &state)){ asm_end("asm_parse_func\n"); }
|
||||
if (asm_parse_func(skip, line, &state)) { asm_end("asm_parse_func\n"); }
|
||||
/* parse stmt */
|
||||
if (asm_parse_stmt(skip, line, &state)) { asm_end("asm_parse_stmt\n"); }
|
||||
|
||||
/* statement closure */
|
||||
if (state == ASM_FUNCTION && (
|
||||
|
|
|
@ -84,8 +84,7 @@ FUNCTION: checkextension, $99
|
|||
|
||||
; constants test
|
||||
VECTOR: dude1, -1, +2, 38865.444
|
||||
FLOAT: dude2, 1
|
||||
STRING: "hello world"
|
||||
|
||||
FUNCTION: foo #1
|
||||
FUNCTION: foo #8
|
||||
MUL_F dude1, dude1, dude1
|
||||
CALL1 print, dude1
|
||||
|
||||
|
|
8
gmqcc.h
8
gmqcc.h
|
@ -369,13 +369,13 @@ typedef struct {
|
|||
} o1;
|
||||
/* operand 2 */
|
||||
union {
|
||||
int16_t s2; /* signed */
|
||||
uint16_t u2; /* unsigned */
|
||||
int16_t s1; /* signed */
|
||||
uint16_t u1; /* unsigned */
|
||||
} o2;
|
||||
/* operand 3 */
|
||||
union {
|
||||
int16_t s3; /* signed */
|
||||
uint16_t u3; /* unsigned */
|
||||
int16_t s1; /* signed */
|
||||
uint16_t u1; /* unsigned */
|
||||
} o3;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue