static void emit_binop_int_arith(Node *node) { SAVE; char *op = NULL; switch (node->type) { case '+': op = "add"; break; case '-': op = "sub"; break; case '*': op = "imul"; break; case '^': op = "xor"; break; case OP_SAL: op = "sal"; break; case OP_SAR: op = "sar"; break; case OP_SHR: op = "shr"; break; case '/': case '%': break; default: error("invalid operator '%d'", node->type); } emit_expr(node->left); push("rax"); emit_expr(node->right); emit("mov %%rax, %%rcx"); pop("rax"); if (node->type == '/' || node->type == '%') { emit("cqto"); emit("idiv %%rcx"); if (node->type == '%') emit("mov %%edx, %%eax"); } else if (node->type == OP_SAL || node->type == OP_SAR || node->type == OP_SHR) { emit("%s %%cl, %%%s", op, get_int_reg(node->left->ctype, 'a')); } else { emit("%s %%rcx, %rax", op); } }
static void emit_gsave(char *varname, Ctype *ctype, int off) { SAVE; assert(ctype->type != CTYPE_ARRAY); maybe_convert_bool(ctype); char *reg = get_int_reg(ctype, 'a'); char *addr = format("%s+%d(%%rip)", varname, off); maybe_emit_bitshift_save(ctype, addr); emit("mov %%%s, %s", reg, addr); }
static void emit_gsave(char *varname, Type *ty, int off) { SAVE; assert(ty->kind != KIND_ARRAY); maybe_convert_bool(ty); char *reg = get_int_reg(ty, 'a'); char *addr = format("%s+%d(%%rip)", varname, off); maybe_emit_bitshift_save(ty, addr); emit("mov #%s, %s", reg, addr); }
static void emit_assign_deref_int(Ctype *ctype, int off) { SAVE; emit("mov (%%rsp), %%rcx"); char *reg = get_int_reg(ctype, 'c'); if (off) emit("mov %%%s, %d(%%rax)", reg, off); else emit("mov %%%s, (%%rax)", reg); pop("rax"); }
static void do_emit_assign_deref(Type *ty, int off) { SAVE; emit("mov (#rsp), #rcx"); char *reg = get_int_reg(ty, 'c'); if (off) emit("mov #%s, %d(#rax)", reg, off); else emit("mov #%s, (#rax)", reg); pop("rax"); }
static void emit_lsave(Ctype *ctype, int off) { SAVE; if (ctype->type == CTYPE_FLOAT) { emit("movss %%xmm0, %d(%%rbp)", off); } else if (ctype->type == CTYPE_DOUBLE) { emit("movsd %%xmm0, %d(%%rbp)", off); } else { maybe_convert_bool(ctype); char *reg = get_int_reg(ctype, 'a'); char *addr = format("%d(%%rbp)", off); maybe_emit_bitshift_save(ctype, addr); emit("mov %%%s, %s", reg, addr); } }
static void emit_lsave(Type *ty, int off) { SAVE; if (ty->kind == KIND_FLOAT) { emit("movss #xmm0, %d(#rbp)", off); } else if (ty->kind == KIND_DOUBLE) { emit("movsd #xmm0, %d(#rbp)", off); } else { maybe_convert_bool(ty); char *reg = get_int_reg(ty, 'a'); char *addr = format("%d(%%rbp)", off); maybe_emit_bitshift_save(ty, addr); emit("mov #%s, %s", reg, addr); } }
static void maybe_emit_bitshift_save(Ctype *ctype, char *addr) { SAVE; if (ctype->bitsize <= 0) return; push("rcx"); push("rdi"); emit("mov $0x%lx, %%rdi", (1 << (long)ctype->bitsize) - 1); emit("and %%rdi, %%rax"); emit("shl $%d, %%rax", ctype->bitoff); emit("mov %s, %%%s", addr, get_int_reg(ctype, 'c')); emit("mov $0x%lx, %%rdi", ~(((1 << (long)ctype->bitsize) - 1) << ctype->bitoff)); emit("and %%rdi, %%rcx"); emit("or %%rcx, %%rax"); pop("rdi"); pop("rcx"); }
static void maybe_emit_bitshift_save(Type *ty, char *addr) { SAVE; if (ty->bitsize <= 0) return; push("rcx"); push("rdi"); emit("mov $0x%lx, #rdi", (1 << (long)ty->bitsize) - 1); emit("and #rdi, #rax"); emit("shl $%d, #rax", ty->bitoff); emit("mov %s, #%s", addr, get_int_reg(ty, 'c')); emit("mov $0x%lx, #rdi", ~(((1 << (long)ty->bitsize) - 1) << ty->bitoff)); emit("and #rdi, #rcx"); emit("or #rcx, #rax"); pop("rdi"); pop("rcx"); }