]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Assembly statement parsing
authorDale Weiler <killfieldengine@gmail.com>
Tue, 1 May 2012 22:05:11 +0000 (18:05 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Tue, 1 May 2012 22:05:11 +0000 (18:05 -0400)
asm.c
data/test.qs
gmqcc.h

diff --git a/asm.c b/asm.c
index 6539e16a07cb168088efd8cc50cc860f377aee3b..24b9e0dcb24de16a6e6812bccbd55929cdb62f6b 100644 (file)
--- a/asm.c
+++ b/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 && (
index 26b0aeb69f63ee8605b9412108f05ce7884d212f..5420d75aa8fc1e1ec2338de74214b2b8efb26ac2 100644 (file)
@@ -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
 
diff --git a/gmqcc.h b/gmqcc.h
index c88c8226cc1a04fd6d5ff1340c556996966a20ce..032566a07e26018d4b90ebc650495409d07f0afc 100644 (file)
--- a/gmqcc.h
+++ b/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;
 
     /*