static void emit_comp(char *inst, Node *node) { SAVE; if (is_flotype(node->left->ctype)) { emit_expr(node->left); push_xmm(0); emit_expr(node->right); pop_xmm(1); if (node->left->ctype->type == CTYPE_FLOAT) emit("ucomiss %%xmm0, %%xmm1"); else emit("ucomisd %%xmm0, %%xmm1"); } else { emit_expr(node->left); push("rax"); emit_expr(node->right); pop("rcx"); int type = node->left->ctype->type; if (type == CTYPE_LONG || type == CTYPE_LLONG) emit("cmp %%rax, %%rcx"); else emit("cmp %%eax, %%ecx"); } emit("%s %%al", inst); emit("movzb %%al, %%eax"); }
static void restore_arg_regs(int nints, int nfloats) { SAVE; for (int i = nfloats - 1; i > 0; i--) pop_xmm(i); for (int i = nints - 1; i >= 0; i--) pop(REGS[i]); }
static void emit_comp(char *inst, char *usiginst, Node *node) { SAVE; if (is_flotype(node->left->ty)) { emit_expr(node->left); push_xmm(0); emit_expr(node->right); pop_xmm(1); if (node->left->ty->kind == KIND_FLOAT) emit("ucomiss #xmm0, #xmm1"); else emit("ucomisd #xmm0, #xmm1"); } else { emit_expr(node->left); push("rax"); emit_expr(node->right); pop("rcx"); int kind = node->left->ty->kind; if (kind == KIND_LONG || kind == KIND_LLONG) emit("cmp #rax, #rcx"); else emit("cmp #eax, #ecx"); } if (is_flotype(node->left->ty) || node->left->ty->usig) emit("%s #al", usiginst); else emit("%s #al", inst); emit("movzb #al, #eax"); }
static void emit_uminus(Node *node) { emit_expr(node->operand); if (is_flotype(node->ctype)) { push_xmm(1); emit("xorpd %%xmm1, %%xmm1"); emit("%s %%xmm1, %%xmm0", (node->ctype->type == CTYPE_DOUBLE ? "subsd" : "subss")); pop_xmm(1); } else { emit("neg %%rax"); } }
static void emit_to_bool(Ctype *ctype) { SAVE; if (is_flotype(ctype)) { push_xmm(1); emit("xorpd %%xmm1, %%xmm1"); emit("%s %%xmm1, %%xmm0", (ctype->type == CTYPE_FLOAT) ? "ucomiss" : "ucomisd"); emit("setne %%al"); pop_xmm(1); } else { emit("cmp $0, %%rax"); emit("setne %%al"); } emit("movzb %%al, %%eax"); }
static void emit_to_bool(Type *ty) { SAVE; if (is_flotype(ty)) { push_xmm(1); emit("xorpd #xmm1, #xmm1"); emit("%s #xmm1, #xmm0", (ty->kind == KIND_FLOAT) ? "ucomiss" : "ucomisd"); emit("setne #al"); pop_xmm(1); } else { emit("cmp $0, #rax"); emit("setne #al"); } emit("movzb #al, #eax"); }
static void emit_binop_float_arith(Node *node) { SAVE; char *op; bool isdouble = (node->ctype->type == CTYPE_DOUBLE); switch (node->type) { case '+': op = (isdouble ? "addsd" : "addss"); break; case '-': op = (isdouble ? "subsd" : "subss"); break; case '*': op = (isdouble ? "mulsd" : "mulss"); break; case '/': op = (isdouble ? "divsd" : "divss"); break; default: error("invalid operator '%d'", node->type); } emit_expr(node->left); push_xmm(0); emit_expr(node->right); emit("%s %%xmm0, %%xmm1", (isdouble ? "movsd" : "movss")); pop_xmm(0); emit("%s %%xmm1, %%xmm0", op); }
static void pop_float_args(int nfloats) { SAVE; for (int i = nfloats - 1; i >= 0; i--) pop_xmm(i); }