/* * txt.c — print a Prog list as Plan 9-flavoured amd64 asm text. * * Format we emit (and that w6a expects): * TEXT name * MOVQ $1, AX * MOVQ AX, name(SB) ; extern symbol * MOVQ off(BP), AX ; local * CMPQ AX, $0 * JE label * RET * label: * * Operand order is Plan 9-ish: source first, dest second. (Same as * AT&T; the convention diverges from Plan 9 only on a few items we * don't yet emit.) */ #include "gc.h" #include const char * anames(int op) { switch (op) { case A_NOP: return "NOP"; case A_TEXT: return "TEXT"; case A_DATA: return "DATA"; case A_DATAW: return "DATAW"; case A_DATAR: return "DATAR"; case A_GLOBL: return "GLOBL"; case A_END: return "END"; case A_MOVQ: return "MOVQ"; case A_MOVL: return "MOVL"; case A_MOVW: return "MOVW"; case A_MOVB: return "MOVB"; case A_MOVZBQ: return "MOVZBQ"; case A_MOVZWQ: return "MOVZWQ"; case A_MOVSXD: return "MOVSXD"; case A_MOVSWQ: return "MOVSWQ"; case A_MOVSBQ: return "MOVSBQ"; case A_MOVSD: return "MOVSD"; case A_ADDSD: return "ADDSD"; case A_SUBSD: return "SUBSD"; case A_MULSD: return "MULSD"; case A_DIVSD: return "DIVSD"; case A_UCOMISD: return "UCOMISD"; case A_CVTTSD2SI: return "CVTTSD2SI"; case A_CVTSI2SD:return "CVTSI2SD"; case A_MOVSS: return "MOVSS"; case A_ADDSS: return "ADDSS"; case A_SUBSS: return "SUBSS"; case A_MULSS: return "MULSS"; case A_DIVSS: return "DIVSS"; case A_UCOMISS: return "UCOMISS"; case A_CVTTSS2SI: return "CVTTSS2SI"; case A_CVTSI2SS:return "CVTSI2SS"; case A_CVTSD2SS:return "CVTSD2SS"; case A_CVTSS2SD:return "CVTSS2SD"; case A_ADDQ: return "ADDQ"; case A_SUBQ: return "SUBQ"; case A_IMULQ: return "IMULQ"; case A_IDIVQ: return "IDIVQ"; case A_DIVQ: return "DIVQ"; case A_CQO: return "CQO"; case A_NEGQ: return "NEGQ"; case A_NOTQ: return "NOTQ"; case A_ANDQ: return "ANDQ"; case A_ORQ: return "ORQ"; case A_XORQ: return "XORQ"; case A_SHLQ: return "SHLQ"; case A_SHRQ: return "SHRQ"; case A_CMPQ: return "CMPQ"; case A_PUSHQ: return "PUSHQ"; case A_POPQ: return "POPQ"; case A_LEAQ: return "LEAQ"; case A_CALL: return "CALL"; case A_RET: return "RET"; case A_JMP: return "JMP"; case A_JE: return "JE"; case A_JNE: return "JNE"; case A_JL: return "JL"; case A_JLE: return "JLE"; case A_JG: return "JG"; case A_JGE: return "JGE"; case A_JB: return "JB"; case A_JBE: return "JBE"; case A_JA: return "JA"; case A_JAE: return "JAE"; case A_JZ: return "JZ"; case A_JNZ: return "JNZ"; case A_JP: return "JP"; case A_SYSCALL: return "SYSCALL"; } return "??"; } const char * rnames(int r) { switch (r) { case D_AX: return "AX"; case D_CX: return "CX"; case D_DX: return "DX"; case D_BX: return "BX"; case D_SP: return "SP"; case D_BP: return "BP"; case D_SI: return "SI"; case D_DI: return "DI"; case D_R8: return "R8"; case D_R9: return "R9"; case D_R10: return "R10"; case D_R11: return "R11"; case D_R12: return "R12"; case D_R13: return "R13"; case D_R14: return "R14"; case D_R15: return "R15"; case D_X0: return "X0"; case D_X1: return "X1"; case D_X2: return "X2"; case D_X3: return "X3"; case D_X4: return "X4"; case D_X5: return "X5"; case D_X6: return "X6"; case D_X7: return "X7"; case D_X8: return "X8"; case D_X9: return "X9"; case D_X10: return "X10"; case D_X11: return "X11"; case D_X12: return "X12"; case D_X13: return "X13"; case D_X14: return "X14"; case D_X15: return "X15"; case D_PSP: return "SP"; case D_PFP: return "FP"; case D_PSB: return "SB"; } return "?"; } static void prAdr(FILE *f, Adr a) { switch (a.type) { case D_NONE: fputs("?", f); break; case D_CONST: fprintf(f, "$%lld", a.offset); break; case D_INDIR: if (a.offset) fprintf(f, "%lld(%s)", a.offset, rnames(a.reg)); else fprintf(f, "(%s)", rnames(a.reg)); break; case D_BRANCH: fputs(a.sym ? a.sym : "?", f); break; case D_EXTERN: fprintf(f, "%s(SB)", a.sym ? a.sym : "?"); break; default: fputs(rnames(a.type), f); } } void txt_emit(FILE *f, Prog *head) { for (Prog *p = head; p; p = p->link) { if (p->label) { fprintf(f, "%s:\n", p->label); if (p->as == A_NOP) continue; } switch (p->as) { case A_NOP: break; case A_TEXT: fprintf(f, "TEXT %s,$%lld\n", p->to.sym ? p->to.sym : "?", p->from.offset); break; case A_RET: fputs("\tRET\n", f); break; case A_SYSCALL: fputs("\tSYSCALL\n", f); break; case A_CQO: fputs("\tCQO\n", f); break; case A_NEGQ: case A_NOTQ: case A_PUSHQ: case A_POPQ: case A_IDIVQ: case A_DIVQ: fprintf(f, "\t%s\t", anames(p->as)); prAdr(f, p->to); fputc('\n', f); break; case A_CALL: case A_JMP: case A_JE: case A_JNE: case A_JL: case A_JLE: case A_JG: case A_JGE: case A_JB: case A_JBE: case A_JA: case A_JAE: case A_JZ: case A_JNZ: case A_JP: fprintf(f, "\t%s\t", anames(p->as)); prAdr(f, p->to); fputc('\n', f); break; default: fprintf(f, "\t%s\t", anames(p->as)); prAdr(f, p->from); fputs(", ", f); prAdr(f, p->to); fputc('\n', f); } } }