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_va_arg(Node *node) { SAVE; emit_expr(node->ap); emit("nop"); push("rcx"); push("rbx"); emit("mov 16(%%rax), %%rcx"); if (is_flotype(node->ctype)) { emit("mov 4(%%rax), %%ebx"); emit("add %%rbx, %%rcx"); emit("add $16, %%ebx"); emit("mov %%ebx, 4(%%rax)"); emit("movsd (%%rcx), %%xmm0"); if (node->ctype->type == CTYPE_FLOAT) emit("cvtpd2ps %%xmm0, %%xmm0"); } else { emit("mov (%%rax), %%ebx"); emit("add %%rbx, %%rcx"); emit("add $8, %%ebx"); emit("mov %%rbx, (%%rax)"); emit("mov (%%rcx), %%rax"); } pop("rbx"); pop("rcx"); }
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 set_reg_nums(List *args) { numgp = numfp = 0; for (Iter *i = list_iter(args); !iter_end(i);) { Node *arg = iter_next(i); if (is_flotype(arg->ctype)) numfp++; else numgp++; } }
static void set_reg_nums(Vector *args) { numgp = numfp = 0; for (int i = 0; i < vec_len(args); i++) { Node *arg = vec_get(args, i); if (is_flotype(arg->ty)) numfp++; else numgp++; } }
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"); } }
// Set the register class for parameter passing to RAX. // 0 is INTEGER, 1 is SSE, 2 is MEMORY. static void emit_builtin_reg_class(Node *node) { Node *arg = vec_get(node->args, 0); assert(arg->ty->kind == KIND_PTR); Type *ty = arg->ty->ptr; if (ty->kind == KIND_STRUCT) emit("mov $2, #eax"); else if (is_flotype(ty)) emit("mov $1, #eax"); else emit("mov $0, #eax"); }
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 classify_args(List *ints, List *floats, List *rest, List *args) { SAVE; int ireg = 0, xreg = 0; int imax = 6, xmax = 8; Iter *iter = list_iter(args); while (!iter_end(iter)) { Node *v = iter_next(iter); if (is_flotype(v->ctype)) list_push((xreg++ < xmax) ? floats : rest, v); else list_push((ireg++ < imax) ? ints : rest, v); } }
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 classify_args(Vector *ints, Vector *floats, Vector *rest, Vector *args) { SAVE; int ireg = 0, xreg = 0; int imax = 6, xmax = 8; for (int i = 0; i < vec_len(args); i++) { Node *v = vec_get(args, i); if (v->ty->kind == KIND_STRUCT) vec_push(rest, v); else if (is_flotype(v->ty)) vec_push((xreg++ < xmax) ? floats : rest, v); else vec_push((ireg++ < imax) ? ints : rest, v); } }
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(Node *node) { SAVE; if (node->ty->kind == KIND_PTR) { emit_pointer_arith(node->kind, node->left, node->right); return; } switch (node->kind) { case '<': emit_comp("setl", "setb", node); return; case OP_EQ: emit_comp("sete", "sete", node); return; case OP_LE: emit_comp("setle", "setna", node); return; case OP_NE: emit_comp("setne", "setne", node); return; } if (is_inttype(node->ty)) emit_binop_int_arith(node); else if (is_flotype(node->ty)) emit_binop_float_arith(node); else error("internal error: %s", node2s(node)); }
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; }
static void emit_binop(Node *node) { SAVE; if (node->ctype->type == CTYPE_PTR) { emit_pointer_arith(node->type, node->left, node->right); return; } switch (node->type) { case '<': emit_comp("setl", node); return; case '>': emit_comp("setg", node); return; case OP_EQ: emit_comp("sete", node); return; case OP_GE: emit_comp("setge", node); return; case OP_LE: emit_comp("setle", node); return; case OP_NE: emit_comp("setne", node); return; } if (is_inttype(node->ctype)) emit_binop_int_arith(node); else if (is_flotype(node->ctype)) emit_binop_float_arith(node); else error("internal error"); }