5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is furnished to do
10 * so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * This is the assembler, gmqas, this is being implemented because I'm
26 * not exactly sure how codegen would work for the C compiler as of yet
27 * and also I plan to allow inline assembly for the compiler.
30 const char *m; /* menomic */
31 const size_t o; /* operands */
32 const size_t l; /* menomic len */
33 } const asm_instr[] = {
34 [INSTR_DONE] = { "DONE" , 0, 4 },
35 [INSTR_MUL_F] = { "MUL_F" , 0, 5 },
36 [INSTR_MUL_V] = { "MUL_V" , 0, 5 },
37 [INSTR_MUL_FV] = { "MUL_FV" , 0, 6 },
38 [INSTR_MUL_VF] = { "MUL_VF" , 0, 6 },
39 [INSTR_DIV_F] = { "DIV" , 0, 3 },
40 [INSTR_ADD_F] = { "ADD_F" , 0, 5 },
41 [INSTR_ADD_V] = { "ADD_V" , 0, 5 },
42 [INSTR_SUB_F] = { "SUB_F" , 0, 5 },
43 [INSTR_SUB_V] = { "DUB_V" , 0, 5 },
44 [INSTR_EQ_F] = { "EQ_F" , 0, 4 },
45 [INSTR_EQ_V] = { "EQ_V" , 0, 4 },
46 [INSTR_EQ_S] = { "EQ_S" , 0, 4 },
47 [INSTR_EQ_E] = { "EQ_E" , 0, 4 },
48 [INSTR_EQ_FNC] = { "ES_FNC" , 0, 6 },
49 [INSTR_NE_F] = { "NE_F" , 0, 4 },
50 [INSTR_NE_V] = { "NE_V" , 0, 4 },
51 [INSTR_NE_S] = { "NE_S" , 0, 4 },
52 [INSTR_NE_E] = { "NE_E" , 0, 4 },
53 [INSTR_NE_FNC] = { "NE_FNC" , 0, 6 },
54 [INSTR_LE] = { "LE" , 0, 2 },
55 [INSTR_GE] = { "GE" , 0, 2 },
56 [INSTR_LT] = { "LT" , 0, 2 },
57 [INSTR_GT] = { "GT" , 0, 2 },
58 [INSTR_LOAD_F] = { "FIELD_F" , 0, 7 },
59 [INSTR_LOAD_V] = { "FIELD_V" , 0, 7 },
60 [INSTR_LOAD_S] = { "FIELD_S" , 0, 7 },
61 [INSTR_LOAD_ENT] = { "FIELD_ENT" , 0, 9 },
62 [INSTR_LOAD_FLD] = { "FIELD_FLD" , 0, 9 },
63 [INSTR_LOAD_FNC] = { "FIELD_FNC" , 0, 9 },
64 [INSTR_ADDRESS] = { "ADDRESS" , 0, 7 },
65 [INSTR_STORE_F] = { "STORE_F" , 0, 7 },
66 [INSTR_STORE_V] = { "STORE_V" , 0, 7 },
67 [INSTR_STORE_S] = { "STORE_S" , 0, 7 },
68 [INSTR_STORE_ENT] = { "STORE_ENT" , 0, 9 },
69 [INSTR_STORE_FLD] = { "STORE_FLD" , 0, 9 },
70 [INSTR_STORE_FNC] = { "STORE_FNC" , 0, 9 },
71 [INSTR_STOREP_F] = { "STOREP_F" , 0, 8 },
72 [INSTR_STOREP_V] = { "STOREP_V" , 0, 8 },
73 [INSTR_STOREP_S] = { "STOREP_S" , 0, 8 },
74 [INSTR_STOREP_ENT] = { "STOREP_ENT", 0, 10},
75 [INSTR_STOREP_FLD] = { "STOREP_FLD", 0, 10},
76 [INSTR_STOREP_FNC] = { "STOREP_FNC", 0, 10},
77 [INSTR_RETURN] = { "RETURN" , 0, 6 },
78 [INSTR_NOT_F] = { "NOT_F" , 0, 5 },
79 [INSTR_NOT_V] = { "NOT_V" , 0, 5 },
80 [INSTR_NOT_S] = { "NOT_S" , 0, 5 },
81 [INSTR_NOT_ENT] = { "NOT_ENT" , 0, 7 },
82 [INSTR_NOT_FNC] = { "NOT_FNC" , 0, 7 },
83 [INSTR_IF] = { "IF" , 0, 2 },
84 [INSTR_IFNOT] = { "IFNOT" , 0, 5 },
85 [INSTR_CALL0] = { "CALL0" , 0, 5 },
86 [INSTR_CALL1] = { "CALL1" , 0, 5 },
87 [INSTR_CALL2] = { "CALL2" , 0, 5 },
88 [INSTR_CALL3] = { "CALL3" , 0, 5 },
89 [INSTR_CALL4] = { "CALL4" , 0, 5 },
90 [INSTR_CALL5] = { "CALL5" , 0, 5 },
91 [INSTR_CALL6] = { "CALL6" , 0, 5 },
92 [INSTR_CALL7] = { "CALL7" , 0, 5 },
93 [INSTR_CALL8] = { "CALL8" , 0, 5 },
94 [INSTR_STATE] = { "STATE" , 0, 5 },
95 [INSTR_GOTO] = { "GOTO" , 0, 4 },
96 [INSTR_AND] = { "AND" , 0, 3 },
97 [INSTR_OR] = { "OR" , 0, 2 },
98 [INSTR_BITAND] = { "BITAND" , 0, 6 },
99 [INSTR_BITOR] = { "BITOR" , 0, 5 }
103 * Some assembler keywords not part of the opcodes above: these are
104 * for creating functions, or constants.
106 const char *const asm_keys[] = {
107 "FLOAT" , /* define float */
108 "VECTOR" , /* define vector */
109 "ENTITY" , /* define ent */
110 "FIELD" , /* define field */
111 "STRING" , /* define string */
115 static char *const asm_getline(size_t *byte, FILE *fp) {
117 ssize_t read = getline(&line, byte, fp);
126 #define asm_rmnewline(L,S) *((L)+*(S)-1) = '\0'
127 #define asm_skipwhite(L) \
128 while((*(L)==' '||*(L)=='\t')) { \
132 void asm_init(const char *file, FILE **fp) {
133 *fp = fopen(file, "r");
137 void asm_close(FILE *fp) {
142 void asm_parse(FILE *fp) {
145 long line = 1; /* current line */
146 size_t size = 0; /* size of line */
148 while ((data = asm_getline(&size, fp)) != NULL) {
151 asm_rmnewline(skip, &size);
153 #define DECLTYPE(X, CODE) \
154 if (!strncmp(X, skip, strlen(X))) { \
155 if (skip[strlen(X)] != ':') { \
156 printf("%li: Missing `:` after decltype\n",line); \
159 skip += strlen(X)+1; \
160 asm_skipwhite(skip); \
161 if(!isalpha(*skip)) { \
162 printf("%li: Invalid identififer: %s\n", line, skip); \
165 size_t offset_code = code_statements_elements+1; \
166 size_t offset_chars = code_strings_elements +1; \
167 size_t offset_globals = code_globals_elements +1; \
168 size_t offset_functions = code_functions_elements +1; \
169 size_t offset_fields = code_fields_elements +1; \
170 size_t offset_defs = code_defs_elements +1; \
172 /* silent unused warnings */ \
174 (void)offset_chars; \
175 (void)offset_globals; \
176 (void)offset_functions; \
177 (void)offset_fields; \
184 DECLTYPE(asm_keys[0], {
185 code_defs_add((prog_section_def){
187 .offset = offset_globals, /* global table */
188 .name = offset_chars /* string table TODO */
190 float f = 0; /*TODO*/
191 code_globals_add(*(int*)&f);
194 DECLTYPE(asm_keys[1], {
195 code_defs_add((prog_section_def){
197 .offset = offset_globals, /* global table */
198 .name = offset_chars /* string table TODO */
203 code_globals_add(*(int*)&f1);
204 code_globals_add(*(int*)&f2);
205 code_globals_add(*(int*)&f3);
207 /* ENTITY */ DECLTYPE(asm_keys[2], {});
208 /* FIELD */ DECLTYPE(asm_keys[3], {});
210 DECLTYPE(asm_keys[4], {
211 code_defs_add((prog_section_def){
213 .offset = offset_globals, /* offset to offset in string table (for data)*/
214 .name = offset_chars /* location of name in string table (for name)*/
218 DECLTYPE(asm_keys[5], {
220 code_defs_add((prog_section_def){
222 .offset = offset_globals,
225 code_globals_add(offset_functions);
226 code_functions_add((prog_section_function){
227 .entry = offset_code,
231 .name = offset_chars,
238 /* if we make it this far then we have statements */
241 for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) {
242 if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) {
249 /* if we made it this far something is wrong */