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 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 save_arg_regs(int nints, int nfloats) { SAVE; assert(nints <= 6); assert(nfloats <= 8); for (int i = 0; i < nints; i++) push(REGS[i]); for (int i = 1; i < nfloats; i++) push_xmm(i); }
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_args(List *vals) { SAVE; Iter *iter = list_iter(vals); while (!iter_end(iter)) { Node *v = iter_next(iter); emit_expr(v); if (is_flotype(v->ctype)) push_xmm(0); else push("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 int emit_args(Vector *vals) { SAVE; int r = 0; for (int i = 0; i < vec_len(vals); i++) { Node *v = vec_get(vals, i); if (v->ty->kind == KIND_STRUCT) { emit_addr(v); r += push_struct(v->ty->size); } else if (is_flotype(v->ty)) { emit_expr(v); push_xmm(0); r += 8; } else { emit_expr(v); push("rax"); r += 8; } } return r; }