8 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
9 #define IS(w, y) !strcmp(w, y)
11 #include "protoparse.h"
16 #define awarn(fmt, ...) \
17 printf("warning:%s:%d: " fmt, asmfn, asmln, ##__VA_ARGS__)
18 #define aerr(fmt, ...) do { \
19 printf("error:%s:%d: " fmt, asmfn, asmln, ##__VA_ARGS__); \
25 OPC_RMD, /* removed or optimized out */
26 OPC_DATA, /* data processing */
27 OPC_DATA_FLAGS, /* data processing + sets flags */
28 OPC_JMP, /* .. and call */
76 #define MAX_OPERANDS 2
88 struct parsed_opr operand[MAX_OPERANDS];
94 static struct parsed_op ops[MAX_OPS];
95 static char labels[MAX_OPS][32];
97 const char *main_regs[] = { "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp" };
99 static int parse_operand(struct parsed_opr *opr,
100 char words[16][256], int wordc, int w, enum op_class cls)
107 aerr("parse_operand w %d, wordc %d\n", w, wordc);
109 for (i = w; i < wordc; i++) {
110 len = strlen(words[i]);
111 if (words[i][len - 1] == ',') {
112 words[i][len - 1] = 0;
118 if (cls == OPC_JMP || cls == OPC_JCC) {
121 if (wordc - w == 3 && IS(words[w + 1], "ptr"))
122 label = words[w + 2];
123 else if (wordc - w == 2 && IS(words[w], "short"))
124 label = words[w + 1];
125 else if (wordc - w == 1)
128 aerr("jump parse error");
130 opr->type = OPT_LABEL;
131 strcpy(opr->name, label);
135 if (wordc - w >= 3) {
136 if (IS(words[w + 1], "ptr")) {
137 if (IS(words[w], "dword"))
138 opr->lmod = OPRM_DWORD;
139 else if (IS(words[w], "word"))
140 opr->lmod = OPRM_WORD;
141 else if (IS(words[w], "byte"))
142 opr->lmod = OPRM_BYTE;
144 aerr("type parsing failed\n");
149 if (wordc - w == 2 && IS(words[w], "offset")) {
150 opr->type = OPT_LABEL;
151 strcpy(opr->name, words[w + 1]);
156 aerr("parse_operand 1 word expected\n");
158 len = strlen(words[w]);
160 if (words[w][0] == '[') {
161 opr->type = OPT_REGMEM;
162 ret = sscanf(words[w], "[%256s]", opr->name);
164 aerr("[] parse failure\n");
167 else if (('0' <= words[w][0] && words[w][0] <= '9')
168 || words[w][0] == '-')
170 opr->type = OPT_CONST;
172 if (len > 1 && words[w][0] == '0')
174 if (words[w][len - 1] == 'h') {
175 words[w][len - 1] = 0;
176 opr->val = strtoul(&words[w][i], &endp, 16);
179 opr->val = strtoul(&words[w][i], &endp, 10);
182 aerr("const parse failed\n");
186 strcpy(opr->name, words[w]);
191 static const struct {
198 { "push", OP_PUSH, OPC_DATA, 1, 1 },
199 { "pop", OP_POP, OPC_DATA, 1, 1 },
200 { "mov" , OP_MOV, OPC_DATA, 2, 2 },
201 { "add", OP_ADD, OPC_DATA_FLAGS, 2, 2 },
202 { "test", OP_TEST, OPC_DATA_FLAGS, 2, 2 },
203 { "cmp", OP_CMP, OPC_DATA_FLAGS, 2, 2 },
204 { "retn", OP_RET, OPC_JMP, 0, 1 },
205 { "call", OP_CALL, OPC_JMP, 1, 1 },
206 { "jmp", OP_JMP, OPC_JMP, 1, 1 },
207 { "jo", OP_JO, OPC_JCC, 1, 1 }, // 70 OF=1
208 { "jno", OP_JNO, OPC_JCC, 1, 1 }, // 71 OF=0
209 { "jc", OP_JC, OPC_JCC, 1, 1 }, // 72 CF=1
210 { "jb", OP_JC, OPC_JCC, 1, 1 }, // 72
211 { "jnc", OP_JNC, OPC_JCC, 1, 1 }, // 73 CF=0
212 { "jae", OP_JNC, OPC_JCC, 1, 1 }, // 73
213 { "jz", OP_JZ, OPC_JCC, 1, 1 }, // 74 ZF=1
214 { "je", OP_JZ, OPC_JCC, 1, 1 }, // 74
215 { "jnz", OP_JNZ, OPC_JCC, 1, 1 }, // 75 ZF=0
216 { "jne", OP_JNZ, OPC_JCC, 1, 1 }, // 75
217 { "jbe", OP_JBE, OPC_JCC, 1, 1 }, // 76 CF=1 || ZF=1
218 { "jna", OP_JBE, OPC_JCC, 1, 1 }, // 76
219 { "ja", OP_JA, OPC_JCC, 1, 1 }, // 77 CF=0 && ZF=0
220 { "jnbe", OP_JA, OPC_JCC, 1, 1 }, // 77
221 { "js", OP_JS, OPC_JCC, 1, 1 }, // 78 SF=1
222 { "jns", OP_JNS, OPC_JCC, 1, 1 }, // 79 SF=0
223 { "jp", OP_JP, OPC_JCC, 1, 1 }, // 7a PF=1
224 { "jpe", OP_JP, OPC_JCC, 1, 1 }, // 7a
225 { "jnp", OP_JNP, OPC_JCC, 1, 1 }, // 7b PF=0
226 { "jpo", OP_JNP, OPC_JCC, 1, 1 }, // 7b
227 { "jl", OP_JL, OPC_JCC, 1, 1 }, // 7c SF!=OF
228 { "jnge", OP_JL, OPC_JCC, 1, 1 }, // 7c
229 { "jge", OP_JGE, OPC_JCC, 1, 1 }, // 7d SF=OF
230 { "jnl", OP_JGE, OPC_JCC, 1, 1 }, // 7d
231 { "jle", OP_JLE, OPC_JCC, 1, 1 }, // 7e ZF=1 || SF!=OF
232 { "jng", OP_JLE, OPC_JCC, 1, 1 }, // 7e
233 { "jg", OP_JG, OPC_JCC, 1, 1 }, // 7f ZF=0 && SF=OF
234 { "jnle", OP_JG, OPC_JCC, 1, 1 }, // 7f
237 static void parse_op(struct parsed_op *op, char words[16][256], int wordc)
243 for (i = 0; i < ARRAY_SIZE(op_table); i++) {
244 if (!IS(words[0], op_table[i].name))
247 for (opr = 0; opr < op_table[i].minopr; opr++) {
248 w = parse_operand(&op->operand[opr],
249 words, wordc, w, op_table[i].cls);
252 for (; w < wordc && opr < op_table[i].maxopr; opr++) {
253 w = parse_operand(&op->operand[opr],
254 words, wordc, w, op_table[i].cls);
260 aerr("unhandled op: '%s'\n", words[0]);
264 aerr("parse_op %s incomplete: %d/%d\n",
267 op->cls = op_table[i].cls;
268 op->op = op_table[i].op;
272 int gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
274 struct parsed_proto pp;
278 ret = proto_parse(fhdr, funcn, &pp);
282 fprintf(fout, "%s %s(", pp.ret_type, funcn);
283 for (i = 0; i < pp.argc; i++) {
286 fprintf(fout, "%s a%d", pp.arg[i].type, i);
288 fprintf(fout, ")\n{\n");
292 fprintf(fout, "}\n\n");
297 int main(int argc, char *argv[])
299 FILE *fout, *fasm, *fhdr;
310 printf("usage:\n%s <.c> <.asm> <hdrf>\n",
316 fhdr = fopen(hdrfn, "r");
317 my_assert_not(fhdr, NULL);
320 fasm = fopen(asmfn, "r");
321 my_assert_not(fasm, NULL);
323 fout = fopen(argv[1], "w");
324 my_assert_not(fout, NULL);
327 while (fgets(line, sizeof(line), fasm))
332 if (*p == 0 || *p == ';')
335 memset(words, 0, sizeof(words));
336 for (wordc = 0; wordc < 16; wordc++) {
337 p = sskip(next_word(words[wordc], sizeof(words[0]), p));
338 if (*p == 0 || *p == ';') {
346 awarn("wordc == 0?\n");
350 // don't care about this:
351 if (words[0][0] == '.'
352 || IS(words[0], "include")
353 || IS(words[0], "assume") || IS(words[1], "segment")
354 || IS(words[0], "align"))
359 if (IS(words[1], "proc")) {
361 aerr("proc '%s' while in_func '%s'?\n",
363 strcpy(func, words[0]);
368 if (IS(words[1], "endp")) {
370 aerr("endp '%s' while not in_func?\n", words[0]);
371 if (!IS(func, words[0]))
372 aerr("endp '%s' while in_func '%s'?\n",
374 gen_func(fout, fhdr, func, pi);
378 memset(&ops, 0, pi * sizeof(ops[0]));
379 memset(labels, 0, pi * sizeof(labels[0]));
386 if (IS(words[1], "="))
387 // lots of work will be have to be done here, but for now..
390 if (pi >= ARRAY_SIZE(ops))
391 aerr("too many ops\n");
393 p = strchr(words[0], ':');
396 if (len > sizeof(labels[0]) - 1)
397 aerr("label too long: %d\n", len);
398 if (labels[pi][0] != 0)
399 aerr("dupe label?\n");
400 memcpy(labels[pi], words[0], len);
405 parse_op(&ops[pi], words, wordc);