📄 gencpu.c
字号:
case absw: case absl: switch(size) { case sz_byte: printf("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: printf("\tput_word(%sa,%s);\n", to, from); break; case sz_long: printf("\tput_long(%sa,%s);\n", to, from); break; default: abort(); } break; case PC16: case PC8r: switch(size) { case sz_byte: printf("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: if (CPU_LEVEL < 2) abort(); printf("\tput_word(%sa,%s);\n", to, from); break; case sz_long: if (CPU_LEVEL < 2) abort(); printf("\tput_long(%sa,%s);\n", to, from); break; default: abort(); } break; case imm: case imm0: case imm1: case imm2: case immi: abort(); break; default: abort(); }}static void genmovemel(UWORD opcode){ char getcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; if (table68k[opcode].size == sz_long) { strcpy(getcode, "get_long(srca)"); } else { strcpy(getcode, "(LONG)(WORD)get_word(srca)"); } printf("\tUWORD mask = nextiword(), bitmask = mask;\n"); genamode(table68k[opcode].smode, "srcreg", table68k[opcode].size, "src", 0, 1); start_brace(); printf("\tint i, bitcnt = 0;\n"); printf("\tfor(i=0;i<16;i++) { bitcnt += bitmask & 1; bitmask >>= 1; }\n"); printf("\tfor(i=0;i<8;i++) { if (mask & 1) { regs.d[i] = %s; srca += %d; } mask >>= 1; }\n", getcode, size); printf("\tfor(i=0;i<8;i++) { if (mask & 1) { regs.a[i] = %s; srca += %d; } mask >>= 1; }\n", getcode, size); if (table68k[opcode].smode == Aipi) printf("\tregs.a[srcreg] = srca;\n");}static void genmovemle(UWORD opcode){ char putcode[100], shiftcode[] = ">>"; int size = table68k[opcode].size == sz_long ? 4 : 2; int mask = 1; if (table68k[opcode].size == sz_long) { strcpy(putcode, "put_long(srca,"); } else { strcpy(putcode, "put_word(srca,"); } printf("\tUWORD mask = nextiword(), bitmask = mask;\n"); genamode(table68k[opcode].smode, "srcreg", table68k[opcode].size, "src", 0, 1); start_brace(); printf("\tint i, bitcnt = 0;\n"); printf("\tULONG rd[8], ra[8];\n"); printf("\tfor(i=0;i<16;i++) { bitcnt += bitmask & 1; bitmask >>= 1; }\n"); printf("\tfor(i=0;i<8;i++) { rd[i] = regs.d[i]; ra[i] = regs.a[i]; }\n"); if (table68k[opcode].smode == Apdi) { printf("\tsrca -= %d*bitcnt;\n", size); printf("\tregs.a[srcreg] = srca;\n"); strcpy(shiftcode, "<<"); mask = 0x8000; } printf("\tfor(i=0;i<8;i++) { if (mask & %d) { %s rd[i]); srca += %d; } mask %s= 1; }\n", mask, putcode, size, shiftcode); printf("\tfor(i=0;i<8;i++) { if (mask & %d) { %s ra[i]); srca += %d; } mask %s= 1; }\n", mask, putcode, size, shiftcode); }typedef enum { flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn, flag_av, flag_sv} flagtypes;static void genflags_normal(flagtypes type, wordsizes size, char *value, char *src, char *dst){ char vstr[100],sstr[100],dstr[100]; char usstr[100],udstr[100]; char unsstr[100],undstr[100]; switch(size) { case sz_byte: strcpy(vstr, "((BYTE)("); strcpy(usstr, "((UBYTE)("); break; case sz_word: strcpy(vstr, "((WORD)("); strcpy(usstr, "((UWORD)("); break; case sz_long: strcpy(vstr, "((LONG)("); strcpy(usstr, "((ULONG)("); break; default: abort(); } strcpy(unsstr, usstr); strcpy(sstr, vstr); strcpy(dstr, vstr); strcat(vstr, value); strcat(vstr,"))"); strcat(dstr, dst); strcat(dstr,"))"); strcat(sstr, src); strcat(sstr,"))"); strcpy(udstr, usstr); strcat(udstr, dst); strcat(udstr,"))"); strcat(usstr, src); strcat(usstr,"))"); strcpy(undstr, unsstr); strcat(unsstr, "-"); strcat(undstr, "~"); strcat(undstr, dst); strcat(undstr,"))"); strcat(unsstr, src); strcat(unsstr,"))"); switch (type) { case flag_logical: case flag_zn: case flag_av: case flag_sv: case flag_addx: case flag_subx: break; case flag_add: start_brace(); printf("ULONG %s = %s + %s;\n", value, dstr, sstr); break; case flag_sub: case flag_cmp: start_brace(); printf("ULONG %s = %s - %s;\n", value, dstr, sstr); break; } switch (type) { case flag_logical: case flag_zn: break; case flag_add: case flag_sub: case flag_addx: case flag_subx: case flag_cmp: case flag_av: case flag_sv: start_brace(); printf("\t"BOOL_TYPE" flgs = %s < 0;\n", sstr); printf("\t"BOOL_TYPE" flgo = %s < 0;\n", dstr); printf("\t"BOOL_TYPE" flgn = %s < 0;\n", vstr); break; } switch(type) { case flag_logical: printf("\tVFLG = CFLG = 0;\n"); printf("\tZFLG = %s == 0;\n", vstr); printf("\tNFLG = %s < 0;\n", vstr); break; case flag_av: printf("\tVFLG = (flgs == flgo) && (flgn != flgo);\n"); break; case flag_sv: printf("\tVFLG = (flgs != flgo) && (flgn != flgo);\n"); break; case flag_zn: printf("\tif (%s != 0) ZFLG = 0;\n", vstr); printf("\tNFLG = %s < 0;\n", vstr); break; case flag_add: printf("\tZFLG = %s == 0;\n", vstr); printf("\tVFLG = (flgs == flgo) && (flgn != flgo);\n"); printf("\tCFLG = regs.x = %s < %s;\n", undstr, usstr); printf("\tNFLG = flgn != 0;\n"); break; case flag_sub: printf("\tZFLG = %s == 0;\n", vstr); printf("\tVFLG = (flgs != flgo) && (flgn != flgo);\n"); printf("\tCFLG = regs.x = %s > %s;\n", usstr, udstr); printf("\tNFLG = flgn != 0;\n"); break; case flag_addx: printf("\tVFLG = (flgs && flgo && !flgn) || (!flgs && !flgo && flgn);\n"); printf("\tregs.x = CFLG = (flgs && flgo) || (!flgn && (flgo || flgs));\n"); break; case flag_subx: printf("\tVFLG = (!flgs && flgo && !flgn) || (flgs && !flgo && flgn);\n"); printf("\tregs.x = CFLG = (flgs && !flgo) || (flgn && (!flgo || flgs));\n"); break; case flag_cmp: printf("\tZFLG = %s == 0;\n", vstr); printf("\tVFLG = (flgs != flgo) && (flgn != flgo);\n"); printf("\tCFLG = %s > %s;\n", usstr, udstr); printf("\tNFLG = flgn != 0;\n"); break; }}static void genflags(flagtypes type, wordsizes size, char *value, char *src, char *dst){#ifdef INTEL_FLAG_OPT switch (type) { case flag_logical: case flag_av: case flag_sv: case flag_zn: case flag_addx: case flag_subx: break; case flag_add: case flag_sub: case flag_cmp: start_brace(); printf("\tULONG %s;\n", value); break; } switch(type) { case flag_av: case flag_sv: case flag_zn: case flag_addx: case flag_subx: break; case flag_logical: if (strcmp(value, "0") == 0) { /* GCC doesn't want to load the constant into a register. * intel_flag_lookup[64] is just the zero flag set. */ printf("\tregflags = intel_flag_lookup[64];\n"); } else { switch(size) { case sz_byte: printf("\t__asm__(\"testb %%0,%%0; lahf; movzbl %%%%ah,%%%%eax; movl intel_flag_lookup(,%%%%eax,4),%%%%eax; movl %%%%eax,regflags\"" ": : \"r\" (%s) : \"%%eax\", \"cc\");", value); break; case sz_word: printf("\t__asm__(\"testw %%0,%%0; lahf; movzbl %%%%ah,%%%%eax; movl intel_flag_lookup(,%%%%eax,4),%%%%eax; movl %%%%eax,regflags\"" ": : \"r\" (%s) : \"%%eax\", \"cc\");", value); break; case sz_long: printf("\t__asm__(\"testl %%0,%%0; lahf; movzbl %%%%ah,%%%%eax; movl intel_flag_lookup(,%%%%eax,4),%%%%eax; movl %%%%eax,regflags\"" ": : \"r\" (%s) : \"%%eax\", \"cc\");", value); break; case sz_unknown: abort(); } } return; case flag_add: /* Of course it would be better to let GCC find a proper register to * compute newv in, but it does not seem to like reloading the 8 bit * regs. */ switch (size) { case sz_byte: printf("\t__asm__(\"addb %%b3,%%b0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&q\" (%s), \"=m\" (regs.x) " ": \"0\" ((BYTE)(%s)), \"qm\" ((BYTE)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_word: printf("\t__asm__(\"addw %%w3,%%w0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&r\" (%s), \"=m\" (regs.x) " ": \"0\" ((WORD)(%s)), \"rmi\" ((WORD)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_long: printf("\t__asm__(\"addl %%3,%%0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&r\" (%s), \"=m\" (regs.x) " ": \"0\" ((LONG)(%s)), \"rmi\" ((LONG)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_unknown: abort(); } return; case flag_sub: switch (size) { case sz_byte: printf("\t__asm__(\"subb %%b2,%%b0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&q\" (%s), \"=m\" (regs.x) " ": \"qmi\" ((BYTE)(%s)), \"0\" ((BYTE)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_word: printf("\t__asm__(\"subw %%w2,%%w0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&r\" (%s), \"=m\" (regs.x) " ": \"rmi\" ((WORD)(%s)), \"0\" ((WORD)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_long: printf("\t__asm__(\"subl %%2,%%0; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al; movb %%%%ah,%%1; movl %%%%eax,regflags \"" ": \"=&r\" (%s), \"=m\" (regs.x) " ": \"rmi\" ((LONG)(%s)), \"0\" ((LONG)(%s)) : \"cc\", \"%%eax\");", value, src, dst); break; case sz_unknown: abort(); } return; case flag_cmp: switch (size) { case sz_byte: printf("\t__asm__(\"movb %%3,%%%%cl; subb %%2,%%%%cl; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al \"" ": \"=a\" (regflags.longflags), \"=&c\" (%s) " ": \"rm\" ((BYTE)(%s)), \"rmi\" ((BYTE)(%s)) : \"cc\");", value, src, dst); break; case sz_word: printf("\t__asm__(\"movw %%3,%%%%cx; subw %%2,%%%%cx; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al \"" ": \"=a\" (regflags.longflags), \"=&c\" (%s) " ": \"rm\" ((WORD)(%s)), \"rmi\" ((WORD)(%s)) : \"cc\");", value, src, dst); break; case sz_long: printf("\t__asm__(\"movl %%3,%%%%ecx; subl %%2,%%%%ecx; lahf; movzbl %%%%ah,%%%%eax;" " movl intel_flag_lookup(,%%%%eax,4),%%%%eax; seto %%%%al \"" ": \"=a\" (regflags.longflags), \"=&c\" (%s) " ": \"rm\" ((LONG)(%s)), \"rmi\" ((LONG)(%s)) : \"cc\");", value, src, dst); break; case sz_unknown: abort(); } return; }#endif genflags_normal(type, size, value, src, dst);}static void gen_opcode(unsigned long int opcode) { start_brace ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -