/* ** VM2GS.C ** ** A vmachine to 65816 conversion utility ** ** by Toshiyasu Morita ** ** Started: 3/26/93 @ 8:36 pm ** ** Info: ** ** Compiler: Watcom C C/386 9.01d ** Tab setting: 4 */ /* ** Things to do: ** ** Write Node allocation routines. ** ** ** */ #include #include #include #define LOOKAHEAD_LINES 5 #define LAST_LINE (LOOKAHEAD_LINES - 1) /* ** Types & Enums */ enum FORMAT {ORCA=1, MERLIN, AVOCET}; typedef struct { char *label; char *operator; char *operand; } LINE_STRUCT; typedef struct { int bytes; char text[1]; } INSTRUCT_STRUCT; /* ** Globals */ char input_file[80], output_file[80]; LINE_STRUCT line_buffer[LOOKAHEAD_LINES]; /* ** Locals */ static int output_format; /************************************* * Start line buffer functions *************************************/ /* ** Intialize line buffers */ void Init_Line_Buffers(void) { int i; for (i=0; i> 16)) return 1; else return 0; } /* ** Check if operator is a load instruction */ int Check_Load(char *operator) { if (!strncmp(operator, "ld", 2)) return 1; else if (!strcmp(operator, "lea")) return 1; else if (!strcmp(operator, "label")) return 1; return 0; } /* ** Five lookahead optimizations */ int Translate_VM32_Look5(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator0, *operand0; char *operator1, *operand1; char *operator2, *operand2; char *operator3, *operand3; char *operator4, *operand4; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; operator1 = line_buffer[1].operator; operand1 = line_buffer[1].operand; operator2 = line_buffer[2].operator; operand2 = line_buffer[2].operand; operator3 = line_buffer[3].operator; operand3 = line_buffer[3].operand; operator4 = line_buffer[4].operator; operand4 = line_buffer[4].operand; if (!strcmp(operator0, "ld.l")) { if (!strcmp(operator1, "st.l") && !strcmp(operator2, "ld.l") && !strcmp(operand1, operand2)) { if (!strcmp(operator3, "add.l") && !strcmp(operand3, "#1")) { if (!strcmp(operator4, "st.l") && !strcmp(operand0, operand4)) { if (*operand0 == '<') { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tldx\t%s+2\n", operand0); fprintf(outfile, "\tsta\t%s\n", operand1); fprintf(outfile, "\tstx\t%s+2\n", operand1); fprintf(outfile, "\tinc\t%s\n", operand0); fprintf(outfile, "\tbne\t*+4\n"); fprintf(outfile, "\tinc\t%s+2\n", operand0); return 5; } else if (*operand0 == '>') { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tldx\t%s+2\n", operand0); fprintf(outfile, "\tsta\t%s\n", operand1); fprintf(outfile, "\tstx\t%s+2\n", operand1); fprintf(outfile, "\tinc\t%s\n", operand0); fprintf(outfile, "\tbne\t*+6\n"); fprintf(outfile, "\tinc\t%s+2\n", operand0); return 5; } } } } } return 0; } /* ** Four lookahead optimizations */ int Translate_VM32_Look4(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator0, *operand0; char *operator1, *operand1; char *operator2, *operand2; char *operator3, *operand3; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; operator1 = line_buffer[1].operator; operand1 = line_buffer[1].operand; operator2 = line_buffer[2].operator; operand2 = line_buffer[2].operand; operator3 = line_buffer[3].operator; operand3 = line_buffer[3].operand; if (!strncmp(operator0, "st", 2) && !strncmp(operator3, "ld", 2) && !strcmp(operator0 + 2, operator3 + 2) && !strcmp(operand0, operand3)) { if (!strncmp(operator1, "ld", 2) && !strncmp(operator2, "st", 2) && !strcmp(operator1 + 2, operator2 + 2) && !strcmp(operand1, operand2)) { if (!strcmp(operator0, "st.b")) { fprintf(outfile, "\tsep\t#$20\n"); fprintf(outfile, "\tlonga\toff\n"); fprintf(outfile, "\tsta\t%s\n", operand0); fprintf(outfile, "\trep\t#$20\n"); fprintf(outfile, "\tlonga\ton\n"); return 4; } else if (!strcmp(operator0, "st.w")) { fprintf(outfile, "\tsta\t%s\n", operand0); return 4; } else if (!strcmp(operator0, "st.l")) { fprintf(outfile, "\tsta\t%s\n", operand0); fprintf(outfile, "\tstx\t%s+2\n", operand0); return 4; } } } return 0; } /* ** Three lookahead optimizations */ int Translate_VM32_Look3(LINE_STRUCT *line_buffer, FILE *outfile) { int temp, word1, word2; char *operator0, *operand0; char *operator1, *operand1; char *operator2, *operand2; char *operator3; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; operator1 = line_buffer[1].operator; operand1 = line_buffer[1].operand; operator2 = line_buffer[2].operator; operand2 = line_buffer[2].operand; operator3 = line_buffer[3].operator; if (!strcmp(operator0, "ld.l") && !strcmp(operator2, "st.l") && Check_Load(operator3)) { if (!strcmp(operator1, "add.l")) { if (!strcmp(operand0, operand2) && !strcmp(operand1, "#1")) { if (*operand0 == '<') { fprintf(outfile, "\tinc\t%s\n", operand0); fprintf(outfile, "\tbne\t*+4\n"); fprintf(outfile, "\tinc\t%s+2\n", operand0); return 3; } } else { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t%s\n", operand1); fprintf(outfile, "\tsta\t%s\n", operand2); fprintf(outfile, "\tlda\t%s+2\n", operand0); fprintf(outfile, "\tadc\t%s+2\n", operand1); fprintf(outfile, "\tsta\t%s+2\n", operand2); return 3; } } if (!strcmp(operator1, "sub.l")) { if (!strcmp(operand0, operand2) && !strcmp(operand1, "#1")) { if (*operand0 == '<') { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tbne\t*+4\n"); fprintf(outfile, "\tdec\t%s+2\n", operand0); fprintf(outfile, "\tdec\t%s\n", operand0); return 3; } } else { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand1); fprintf(outfile, "\tsta\t%s\n", operand2); fprintf(outfile, "\tlda\t%s+2\n", operand0); fprintf(outfile, "\tsbc\t%s+2\n", operand1); fprintf(outfile, "\tsta\t%s+2\n", operand2); return 3; } } return 0; } if (!strcmp(operator0, "ext.bl") && !strcmp(operator1, "cmp.l")) { #if 0 if (!strcmp(operator2, "blt")) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand1); fprintf(outfile, "\tbvs\t*+5\n"); fprintf(outfile, "\teor\t#$8000\n"); fprintf(outfile, "\tbmi\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } if (!strcmp(operator2, "ble")) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand1); fprintf(outfile, "\tbeq\t*+9\n"); fprintf(outfile, "\tbvs\t*+5\n"); fprintf(outfile, "\teor\t#$8000\n"); fprintf(outfile, "\tbmi\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } #endif if (!strcmp(operator2, "beq")) { fprintf(outfile, "\tcmp\t%s\n", operand1); fprintf(outfile, "\tbne\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } #if 0 if (!strcmp(operator2, "bge")) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand1); fprintf(outfile, "\tbvc\t*+5\n"); fprintf(outfile, "\teor\t#$8000\n"); fprintf(outfile, "\tbmi\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } if (!strcmp(operator2, "bgt")) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand1); fprintf(outfile, "\tbeq\t*+12\n"); fprintf(outfile, "\tbvc\t*+5\n"); fprintf(outfile, "\teor\t#$8000\n"); fprintf(outfile, "\tbmi\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } #endif if (!strcmp(operator2, "bne")) { fprintf(outfile, "\tcmp\t%s\n", operand1); fprintf(outfile, "\tbeq\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand2); return 3; } } return 0; } /* ** Two lookahead optimizations */ int Translate_VM32_Look2(LINE_STRUCT *line_buffer, FILE *outfile) { int temp, temp2, word1, word2; char *operator0, *operand0; char *operator1, *operand1; char *operator2, *operand2; char *operator3; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; operator1 = line_buffer[1].operator; operand1 = line_buffer[1].operand; operator2 = line_buffer[2].operator; operand2 = line_buffer[2].operand; operator3 = line_buffer[3].operator; if (!strcmp(operator0, "ld.w")) { if (!strcmp(operand0, "#0") && !strcmp(operator1, "st.w") && !memcmp(operator2, "ld", 2)) { fprintf(outfile, "\tstz\t%s\n", operand1); return 2; } return 0; } if (!strcmp(operator0, "ld.l")) { /* Check for ld.l foo, st.b foo */ if (Check_Load(operator1) && !strcmp(operand0, operand1)) { fputs("* redundant ld.l foo, st.b foo removed\n", outfile); return 2; } if (!strcmp(operator1, "st.l")) { if ((*operand0 == '#') && (atol(operand0+1) < 256) && Check_Load(operator2)) { fprintf(outfile, "* < 256 load optimization\n"); if (!strcmp(operand0+1, "0")) fprintf(outfile, "\tstz\t%s\n", operand1); else { fprintf(outfile, "\tlda\t%s\n", operand0); fprintf(outfile, "\tsta\t%s\n", operand1); } fprintf(outfile, "\tstz\t%s+2\n", operand1); return 2; } else if (!strcmp(operand0, operand1)) { if (Check_Load(operator2)) { fprintf(outfile, "* ld.l foo, st.l foo removed\n"); return 2; } } } if (!strcmp(operator1, "push.l") && Check_Load(operator2)) { if (*operand0 == '<') { fprintf(outfile, "\tpei\t%s+2\n", operand0); fprintf(outfile, "\tpei\t%s\n", operand0); return 2; } } if ((*operand0 == '<') && !*operand1) { if (!strcmp(operator1, "ldi.b") || !strcmp(operator1, "ldi.w")) { fprintf(outfile, "\tlda\t[%s]\n", operand0); return 2; } else if (!strcmp(operator1, "ldi.l")) { fprintf(outfile, "\tldy\t#2\n"); fprintf(outfile, "\tlda\t[%s],y\n", operand0); fprintf(outfile, "\ttax\n"); fprintf(outfile, "\tlda\t[%s]\n", operand0); return 2; } } return 0; } if (!strcmp(operator0, "st.b")) { if (!strcmp(operator1, "ld.b") && !strcmp(operand0, operand1)) { fprintf(outfile, "\tsep\t#$20\n"); fprintf(outfile, "\tlonga\toff\n"); fprintf(outfile, "\tsta\t%s\n", operand0); fprintf(outfile, "\trep\t#$20\n"); fprintf(outfile, "\tlonga\ton\n"); return 2; } return 0; } if (!strcmp(operator0, "st.w")) { if (!strcmp(operator1, "ld.w") && !strcmp(operand0, operand1)) { fprintf(outfile, "\tsta\t%s\n", operand0); return 2; } return 0; } /* check for st.l foo, ld.l foo */ if (!strcmp(operator0, "st.l")) { if (!strcmp(operator1, "ld.l") && !strcmp(operand0, operand1)) { fprintf(outfile, "\tsta\t%s\n", operand0); fprintf(outfile, "\tstx\t%s+2\n", operand0); return 2; } return 0; } /* check for add.l, st.l */ if (!strcmp(operator0, "add.l")) { if (!strcmp(operator1, "st.l") && Check_Load(operator2)) { fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t%s\n", operand0); fprintf(outfile, "\tsta\t%s\n", operand1); fprintf(outfile, "\ttxa\n"); fprintf(outfile, "\tadc\t%s+2\n", operand0); fprintf(outfile, "\tsta\t%s+2\n", operand1); return 2; } } /* check for sub.l, st.l */ if (!strcmp(operator0, "sub.l")) { if (!strcmp(operator1, "st.l") && Check_Load(operator2)) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand0); fprintf(outfile, "\tsta\t%s\n", operand1); fprintf(outfile, "\ttxa\n"); fprintf(outfile, "\tsbc\t%s+2\n", operand0); fprintf(outfile, "\tsta\t%s+2\n", operand1); return 2; } } /* check for jsl x, rtl */ if (!strcmp(operator0, "jsr") && !strcmp(operator1, "ret")) { fprintf(outfile, "\tjml\t%s\n", operand0); return 2; } if (!strcmp(operator0, "lea") && (*operand0 == '>') && !strcmp(operator1, "push.l") && !*operand1) { fprintf(outfile, "\tpea\t^%s\n", operand0 + 1); fprintf(outfile, "\tpea\t%s\n", operand0 + 1); return 2; } if (!strcmp(operator0, "pop") && !strcmp(operator1, "unlk")) { temp = atol(operand0 + 1); temp2 = atol(operand1 + 1); fprintf(outfile, "\ttay\n"); fprintf(outfile, "\tlda\t%d,s\n", temp + 1); fprintf(outfile, "\ttcd\n"); fprintf(outfile, "\ttsc\n"); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t#%d\n", temp + temp2 + 2); fprintf(outfile, "\ttcs\n"); fprintf(outfile, "\ttya\n"); return 2; } return 0; } /* ** Translate VM32 code */ int Translate_VM32_Loads(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator, *operand; operator = line_buffer[0].operator; operand = line_buffer[0].operand; if (!strcmp(operator, "ld.b")) { fprintf(outfile, "\tlda\t%s\n", operand); return 1; } else if (!strcmp(operator, "ld.w")) { fprintf(outfile, "\tlda\t%s\n", operand); return 1; } else if (!strcmp(operator, "ld.l")) { if ((*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tldx\t%s+2\n", operand); return 1; } else if (*operand == '#') { if (Check_Repeat_Constant(operand)) { fprintf(outfile, "\tlda\t%s\n", operand); fputs("\ttax\n", outfile); return 1; } else { fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tldx\t#^%s\n", operand + 1); return 1; } } } else if (!strcmp(operator, "ldi.b") || !strcmp(operator, "ldi.w")) { if (!*operand) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tlda\t[') { fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tlda\t%s+2\n", operand); fprintf(outfile, "\tsta\tscratch+2\n"); fprintf(outfile, "\tlda\t[') { fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tlda\t%s+2\n", operand); fprintf(outfile, "\tsta\tscratch+2\n"); fprintf(outfile, "\tldy\t#2\n"); fprintf(outfile, "\tlda\t[') || (*operand == '#')) { fprintf(outfile, "\tsep\t#$20\n"); fprintf(outfile, "\tlonga\toff\n"); fprintf(outfile, "\tsta\t%s\n", operand); fprintf(outfile, "\trep\t#$20\n"); fprintf(outfile, "\tlonga\ton\n"); return 1; } } else if (!strcmp(operator, "st.w")) { if ((*operand == '<') || (*operand == '>') || (*operand == '#')) { fprintf(outfile, "\tsta\t%s\n", operand); return 1; } } else if (!strcmp(operator, "st.l")) { if ((*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tsta\t%s\n", operand); fprintf(outfile, "\tstx\t%s+2\n", operand); return 1; } } else if (!strcmp(operator, "sti.b")) { if (*operand == '<') { fprintf(outfile, "\tsep\t#$20\n"); fprintf(outfile, "\tlonga\toff\n"); fprintf(outfile, "\tsta\t[%s]\n", operand); fprintf(outfile, "\trep\t#$20\n"); fprintf(outfile, "\tlonga\ton\n"); return 1; } else if (*operand == '>') { fprintf(outfile, "\ttay\n"); fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tlda\t%s+2\n", operand); fprintf(outfile, "\tsta\tscratch+2\n"); fprintf(outfile, "\ttya\n"); fprintf(outfile, "\tsep\t#$20\n"); fprintf(outfile, "\tlonga\toff\n"); fprintf(outfile, "\tsta\t[scratch]\n"); fprintf(outfile, "\trep\t#$20\n"); fprintf(outfile, "\tlonga\ton\n"); return 1; } } else if (!strcmp(operator, "sti.w")) { if (*operand == '<') { fprintf(outfile, "\tsta\t[%s]\n", operand); return 1; } else if (*operand == '>') { fprintf(outfile, "\ttay\n"); fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tlda\t%s+2\n", operand); fprintf(outfile, "\tsta\tscratch+2\n"); fprintf(outfile, "\ttya\n"); fprintf(outfile, "\tsta\t[scratch]\n"); return 1; } } else if (!strcmp(operator, "sti.l")) { if (*operand == '<') { fprintf(outfile, "\tsta\t[%s]\n", operand); fprintf(outfile, "\tldy\t#2\n"); fprintf(outfile, "\tsta\t[%s],y\n", operand); return 1; } else if (*operand == '>') { fprintf(outfile, "\tpha\n"); fprintf(outfile, "\tlda\t%s\n", operand); fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tlda\t%s+2\n", operand); fprintf(outfile, "\tsta\tscratch+2\n"); fprintf(outfile, "\tpla\n"); fprintf(outfile, "\tsta\t[scratch]\n"); fprintf(outfile, "\tldy\t#2\n"); fprintf(outfile, "\tsta\t[scratch],y\n"); return 1; } } return 0; } /* ** Output TAY TXA */ void Swap_Register_In(FILE *outfile) { fprintf(outfile, "\ttay\n"); fprintf(outfile, "\ttxa\n"); } /* ** Output TAX TYA */ void Swap_Register_Out(FILE *outfile) { fprintf(outfile, "\ttax\n"); fprintf(outfile, "\ttya\n"); } /* ** Set short x */ void Set_Short_X(FILE *outfile) { fprintf(outfile, "\tlongx\toff\n"); fprintf(outfile, "\tsep\t#$10\n"); } /* ** Set long x */ void Set_Long_X(FILE *outfile) { fprintf(outfile, "\tlongx\ton\n"); fprintf(outfile, "\trep\t#$10\n"); } /* ** Translate VM32 shifts */ int Translate_VM32_Shifts(LINE_STRUCT *line_buffer, FILE *outfile) { int i, temp; char *operator0, *operand0; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; if (!strcmp(operator0, "lsh.l")) { if (*operand0 == '#') { fprintf(outfile, "\tstx\tscratch\n"); temp = atol(operand0+1) & 31; for (i=0; i')) fprintf(outfile, "\tadc\t%s+2\n", operand); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "and.w")) { if ((*operand == '#') || (*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tand\t%s\n", operand); return 1; } } else if (!strcmp(operator, "and.l")) { if (*operand == '#') { fprintf(outfile, "\tand\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\tand\t#^%s\n", operand + 1); Swap_Register_Out(outfile); return 1; } else if ((*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tand\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\tand\t%s+2\n", operand); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "eor.l")) { if (*operand == '#') { fprintf(outfile, "\teor\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\teor\t#^%s\n", operand + 1); Swap_Register_Out(outfile); return 1; } else if ((*operand == '<') && (*operand == '>')) { fprintf(outfile, "\teor\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\teor\t%s+2\n", operand); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "lea")) { if (*operand == '<') { fprintf(outfile, "\ttsc\n"); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t#%s\n", operand+1); fprintf(outfile, "\tldx\t#0\n"); return 1; } else if (*operand == '>') { fprintf(outfile, "\tlda\t#%s\n", operand+1); fprintf(outfile, "\tldx\t#^%s\n", operand+1); return 1; } } else if (!strcmp(operator, "neg.l")) { if (!*operand) { fprintf(outfile, "\teor\t#$ffff\n"); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t#1\n"); Swap_Register_In(outfile); fprintf(outfile, "\teor\t#$ffff\n"); fprintf(outfile, "\tadc\t#0\n"); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "or.l")) { if ((*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tora\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\tora\t%s+2", operand); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "sub.l")) { if (*operand == '#') { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\tsbc\t#^%s\n", operand + 1); Swap_Register_Out(outfile); return 1; } else if ((*operand == '<') || (*operand == '>')) { fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand); Swap_Register_In(outfile); fprintf(outfile, "\tsbc\t%s+2\n", operand); Swap_Register_Out(outfile); return 1; } } else if (!strcmp(operator, "muli.l")) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tmul4\scratch,%s\n", operand); fprintf(outfile, "\tlda\tscratch\n"); fprintf(outfile, "\tldx\tscratch+2\n"); } else if (!strcmp(operator, "divi.l")) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tdiv4\tscratch,%s,scratch\n", operand); fprintf(outfile, "\tlda\tscratch\n"); fprintf(outfile, "\tldx\tscratch+2\n"); return 1; } else if (!strcmp(operator, "ext.bl")) { if (!*operand) { fprintf(outfile, "\tand\t#$00ff\n"); fprintf(outfile, "\tldx\t#0\n"); fprintf(outfile, "\tbit\t#$0080\n"); fprintf(outfile, "\tbeq\t*+6\n"); fprintf(outfile, "\tora\t#$ff00\n"); fprintf(outfile, "\tdex\n"); return 1; } } else if (!strcmp(operator, "ext.wl")) { if (!*operand) { fprintf(outfile, "\tldx\t#0\n"); fprintf(outfile, "\tbit\t#$8000\n"); fprintf(outfile, "\tbeq\t*+3\n"); fprintf(outfile, "\tdex\n"); return 1; } } return 0; } /* ** Translate Stack stuff */ int Translate_VM32_Stack_Stuff(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator, *operand; operator = line_buffer[0].operator; operand = line_buffer[0].operand; if (!strcmp(operator, "pop.w")) { fprintf(outfile, "\tpla\n"); return 1; } else if (!strcmp(operator, "pop.l")) { fprintf(outfile, "\tpla\n"); fprintf(outfile, "\tplx\n"); return 1; } else if (!strcmp(operator, "push.w")) { fprintf(outfile, "\tpha\n"); return 1; } else if (!strcmp(operator, "push.l")) { if (!*operand) { fprintf(outfile, "\tphx\n"); fprintf(outfile, "\tpha\n"); return 1; } else if (*operand == '#') { fprintf(outfile, "\tpea\t^%s\n", operand + 1); fprintf(outfile, "\tpea\t%s\n", operand + 1); return 1; } else if (*operand == '<') { fprintf(outfile, "\tpei\t%s+2\n", operand); fprintf(outfile, "\tpei\t%s\n", operand); return 1; } } else if (!strcmp(operator, "pop")) { if (*operand == '#') { fprintf(outfile, "\ttay\n"); fprintf(outfile, "\ttsc\n"); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t%s\n", operand); fprintf(outfile, "\ttcs\n"); fprintf(outfile, "\ttya\n"); return 1; } } return 0; } /* ** Translate call stuff */ int Translate_VM32_Call_Stuff(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator, *operand; operator = line_buffer[0].operator; operand = line_buffer[0].operand; if (!strcmp(operator, "jmp")) { fprintf(outfile, "\tjmp\t%s\n", operand); return 1; } else if (!strcmp(operator, "jmpi")) { fprintf(outfile, "\tsep\t#$10\n"); fprintf(outfile, "\tlongi\toff\n"); fprintf(outfile, "\tphx\n"); fprintf(outfile, "\trep\t#$10\n"); fprintf(outfile, "\tlongi\ton\n"); fprintf(outfile, "\tdec\ta\n"); fprintf(outfile, "\tpha\n"); fprintf(outfile, "\trtl\n"); return 1; } else if (!strcmp(operator, "jsr")) { fprintf(outfile, "\tjsl\t%s\n", operand); return 1; } else if (!strcmp(operator, "jsri")) { Set_Short_X(outfile); fprintf(outfile, "\tphx\n"); Set_Long_X(outfile); fprintf(outfile, "\tdec\ta\n"); fprintf(outfile, "\tpha\n"); fprintf(outfile, "\trtl\n"); return 1; } else if (!strcmp(operator, "ret")) { fprintf(outfile, "\trtl\n"); return 1; } else if (!strcmp(operator, "link")) { fprintf(outfile, "\ttsc\n"); fprintf(outfile, "\tsec\n"); fprintf(outfile, "\tsbc\t%s\n", operand); fprintf(outfile, "\ttcs\n"); fprintf(outfile, "\tphd\n"); fprintf(outfile, "\ttcd\n"); return 1; } else if (!strcmp(operator, "unlk")) { fprintf(outfile, "\ttay\n"); fprintf(outfile, "\tpld\n"); fprintf(outfile, "\ttsc\n"); fprintf(outfile, "\tclc\n"); fprintf(outfile, "\tadc\t%s\n", operand); fprintf(outfile, "\ttcs\n"); fprintf(outfile, "\ttya\n"); return 1; } return 0; } /* ** Handle compares */ int Translate_VM32_Compares(LINE_STRUCT *line_buffer, FILE *outfile) { char *operator0, *operand0, *operator1, *operand1; operator0 = line_buffer[0].operator; operand0 = line_buffer[0].operand; operator1 = line_buffer[1].operator; operand1 = line_buffer[1].operand; if (!strcmp(operator0, "cmp.l") && !strcmp(operator1, "blt")) { if (*operand0 == '#') { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0); fprintf(outfile, "\tbcs\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } else if ((*operand0 == '<') || (*operand0 == '>')) { fprintf(outfile, "\tsta\t')) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0 + 1); fprintf(outfile, "\tbeq\t*+7\n"); fprintf(outfile, "\tbcs\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } } else if (!strcmp(operator0, "cmp.l") && !strcmp(operator1, "beq")) { if (*operand0 == '#') { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0); fprintf(outfile, "\tbne\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } else if ((*operand0 == '<') || (*operand0 == '>')) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0 + 1); fprintf(outfile, "\tbne\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } } else if (!strcmp(operator0, "cmp.l") && !strcmp(operator1, "bge")) { if (*operand0 == '#') { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0); fprintf(outfile, "\tbcc\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } else if ((*operand0 == '<') || (*operand0 == '>')) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0 + 1); fprintf(outfile, "\tbcc\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } } else if (!strcmp(operator0, "cmp.l") && !strcmp(operator1, "bgt")) { if (*operand0 == '#') { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0); fprintf(outfile, "\tbcc\t*+7\n"); fprintf(outfile, "\tbeq\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } else if ((*operand0 == '<') || (*operand0 == '>')) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0 + 1); fprintf(outfile, "\tbcc\t*+7\n"); fprintf(outfile, "\tbeq\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } } else if (!strcmp(operator0, "cmp.l") && !strcmp(operator1, "bne")) { if (*operand0 == '#') { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0); fprintf(outfile, "\tbeq\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } else if ((*operand0 == '<') || (*operand0 == '>')) { fprintf(outfile, "\tsta\tscratch\n"); fprintf(outfile, "\tstx\tscratch+2\n"); fprintf(outfile, "\tCMP4\tscratch,%s\n", operand0 + 1); fprintf(outfile, "\tbeq\t*+5\n"); fprintf(outfile, "\tjmp\t%s\n", operand1); return 2; } } return 0; } /* ** Handle pseudo-ops */ int Translate_Pseudo_Ops(LINE_STRUCT *line_buffer, FILE *outfile) { char *label, *operator, *operand; label = line_buffer[0].label; operator = line_buffer[0].operator; operand = line_buffer[0].operand; if (!strcmp(operator, "equ")) { fprintf(outfile, "%s\t%s\t%s\n", label, operator, operand); return 1; } else if (!strcmp(operator, "label")) { fprintf(outfile, "%s\tanop\n", label); return 1; } else if (!strcmp(operator, "start")) { fprintf(outfile, "%s\tstart\n", label); fprintf(outfile, "\tlonga\ton\n"); fprintf(outfile, "\tlongi\ton\n"); return 1; } else if (!strcmp(operator, "end")) { fprintf(outfile, "%s\tend\n", label); return 1; } else if (!strcmp(operator, "entry")) { fprintf(outfile, "%s\tentry\n", label); return 1; } else if (!strcmp(operator, "ds")) { fprintf(outfile, "%s\tds\t%s\n", label, operand); return 1; } else if (!strcmp(operator, "import")) { return 1; } else if (!strcmp(operator, "export")) { return 1; } else if (!strcmp(operator, "data")) { fprintf(outfile, "%s\tdata\n", label); return 1; } else if (!strcmp(operator, "dc.b")) { fprintf(outfile, "\tdc\ti1'%s'\n", operand); return 1; } else if (*operator == '!') { fprintf(outfile, "\t%s\t%s\n", operator+1, operand); return 1; } return 0; } /* ** Translate line */ int Translate_Line(FILE *infile, FILE *outfile) { int temp; temp = Translate_VM32_Look5(line_buffer, outfile); if (!temp) temp = Translate_VM32_Look4(line_buffer, outfile); if (!temp) temp = Translate_VM32_Look3(line_buffer, outfile); if (!temp) temp = Translate_VM32_Look2(line_buffer, outfile); if (!temp) temp = Translate_VM32_Loads(line_buffer, outfile); if (!temp) temp = Translate_VM32_Stores(line_buffer, outfile); if (!temp) temp = Translate_VM32_Arithmetic(line_buffer, outfile); if (!temp) temp = Translate_Pseudo_Ops(line_buffer, outfile); if (!temp) temp = Translate_VM32_Arithmetic(line_buffer, outfile); if (!temp) temp = Translate_VM32_Shifts(line_buffer, outfile); if (!temp) temp = Translate_VM32_Compares(line_buffer, outfile); if (!temp) temp = Translate_VM32_Stack_Stuff(line_buffer, outfile); if (!temp) temp = Translate_VM32_Call_Stuff(line_buffer, outfile); if (!temp) { fprintf(outfile, "* Unknown operation: %s %s %s\n", line_buffer[0].label, line_buffer[0].operator, line_buffer[0].operand); temp = 1; } assert(temp <= LOOKAHEAD_LINES); return temp; } /* ** Translate */ void Translate_File(FILE *infile, FILE *outfile) { int i, lines; fprintf(outfile, "\tmcopy\t13/orcainclude/m16.orca\n"); for (i=0; i