static inline void emit_nop(struct jit_ctx *ctx) { emit_instr(ctx, nop); }
static inline void emit_addu(unsigned int dst, unsigned int src1, unsigned int src2, struct jit_ctx *ctx) { emit_instr(ctx, addu, dst, src1, src2); }
void write_syntax(FILE *out, Syntax *syntax){ printf("write_syntax\n"); if(syntax->type == IMMEDIATE){ printf("case gen immediate\n"); emit_instr_format(out, "mov", "$%d, %%eax", syntax->immediate->value); } else if (syntax->type == VARIABLE) { printf("case gen var\n"); emit_instr_format(out, "mov", "-%d(%%ebp), %%eax", 4*(syntax->variable->var_index+1)); } else if (syntax->type == BINARY_OPERATOR){ printf("case gen binary\n"); BinaryExpression *binary_syntax = syntax->binary_expression; //reserve space for temporary write_syntax(out, binary_syntax->left); emit_instr(out, "sub", "$4, %esp"); emit_instr(out, "mov", "%eax, 0(%esp)"); write_syntax(out, binary_syntax->right); if(binary_syntax->binary_type == MULTIPLICATION){ emit_instr(out, "mull", "0(%esp)"); //emit_instr(out, "mull", "%ebx"); emit_instr(out, "add", "$4, %esp"); } else if (binary_syntax->binary_type == DIVISION) { //edx:eax / 0(%esp) emit_instr(out, "mov", "$0, %edx"); emit_instr(out, "xchg", "0(%esp), %eax"); emit_instr(out, "divl", "0(%esp)"); emit_instr(out, "add", "$4, %esp"); } else if (binary_syntax->binary_type == MOD) { emit_instr(out, "mov", "$0, %edx"); emit_instr(out, "xchg", "0(%esp), %eax"); emit_instr(out, "divl", "0(%esp)"); emit_instr(out, "mov", "%edx, %eax"); emit_instr(out, "add", "$4, %esp"); } else if (binary_syntax->binary_type == ADDITION){ emit_instr(out, "add", "0(%esp), %eax"); //emit_instr(out, "add", "%ebx, %eax"); //TODO: check if this instruction redundant emit_instr(out, "add", "$4, %esp"); } else if (binary_syntax->binary_type == SUBTRACTION) { emit_instr(out, "sub", "%eax, 0(%esp)"); emit_instr(out, "mov", "0(%esp), %eax"); emit_instr(out, "add", "$4, %esp"); } else if (binary_syntax->binary_type == COMPARISION) { emit_instr(out, "xor", "0(%esp), %eax"); emit_instr(out, "add", "$4, %esp"); } } else if (syntax->type == ASSIGNMENT) { printf("case gen assignment\n"); write_syntax(out, syntax->assignment->expression); emit_instr_format(out, "mov", "%%eax, -%d(%%ebp)", 4*(syntax->assignment->var_index+1)); } else if (syntax->type == SHOW_STATEMENT){ printf("case get SHOW statement"); if(syntax->show_statement->decOrHex == 'd'){ emit_instr_format(out, "pushl", "-%d(%%ebp)", 4*(syntax->show_statement->var->variable->var_index+1)); emit_instr(out, "pushl", "$.LC0"); emit_instr(out, "call", "_printf"); } else if (syntax->show_statement->decOrHex == 'h') { emit_instr_format(out, "pushl", "-%d(%%ebp)", 4*(syntax->show_statement->var->variable->var_index+1)); emit_instr(out, "pushl", "$.LC1"); emit_instr(out, "call", "_printf"); } } else if (syntax->type == IF_STATEMENT){ char *label; printf("case if statement kaa"); write_syntax(out, syntax->if_statement->condition); emit_instr(out, "test", "%eax, %eax"); label = gen_label("LC"); emit_instr_format(out, "jne", "%s", label); write_syntax(out, syntax->if_statement->then); emit_label(out, label); //emit_instr(out, "call", "_printf"); } else if (syntax->type == FOR_STATEMENT) { char *start_label; char *end_label; if(syntax->for_statement->startNum->type == IMMEDIATE){ emit_instr_format(out, "mov", "$%d, %%edi", syntax->for_statement->startNum->immediate->value); } else if (syntax->for_statement->startNum->type == VARIABLE) { emit_instr_format(out, "mov", "-%d(%%ebp), %%edi", 4*(syntax->for_statement->startNum->variable->var_index+1)); } if(syntax->for_statement->stopNum->type == IMMEDIATE){ emit_instr_format(out, "mov", "$%d, %%esi", syntax->for_statement->stopNum->immediate->value); } else if (syntax->for_statement->stopNum->type == VARIABLE) { emit_instr_format(out, "mov", "-%d(%%ebp), %%esi", 4*(syntax->for_statement->stopNum->variable->var_index+1)); } start_label = gen_label("LC"); end_label = gen_label("LC"); emit_label(out, start_label); emit_instr(out, "cmp", "%edi, %esi"); //confuse which jump condition to use. emit_instr_format(out, "jg", "%s", end_label); write_syntax(out, syntax->for_statement->expression); emit_instr(out, "inc", "%esi"); emit_instr_format(out, "jmp", "%s", start_label); emit_label(out, end_label); } else if (syntax->type == INPUT) { //printf("gen INPUT\n"); List *lines = syntax->input->lines; int i; for (i = list_length(lines)-1; i >= 0; i--) { //printf("*"); write_syntax(out, list_get(lines, i)); } } else if(syntax->type = MINUS){ printf("gen minus\n"); write_syntax(out,syntax->minus->expression); emit_instr(out, "xor", "%ebx, %ebx"); emit_instr(out, "sub", "%eax, %ebx"); emit_instr(out, "mov", "%ebx, %eax"); } else { printf("last case\n"); } /*else if(syntax->type = MINUS){ write_syntax(out,syntax->expression); emit_instr(out, "sub", "0(%esp), %eax"); }*/ }
void write_footer(FILE *out){ emit_instr(out, "pushl", "$0"); emit_instr(out, "leave", ""); emit_instr(out, "ret", ""); }
void write_header(FILE *out){ emit_header(out, ".data\n.LC0: .ascii \"%d\\n\\0\"\n.LC1: .ascii \"%x\\n\\0\"\n.text\n .global _main\n_main:\n"); emit_instr(out, "pushl", "%ebp"); emit_instr(out, "movl", "%esp, %ebp"); emit_instr(out, "sub", "$104, %esp"); }
static void emit_instr(lima_gp_instruction_t* instr, lima_gp_ir_instr_t* ir_instr) { static const lima_gp_instruction_t nop_instr = { .mul0_src0 = lima_gp_src_unused, .mul0_src1 = lima_gp_src_unused, .mul1_src0 = lima_gp_src_unused, .mul1_src1 = lima_gp_src_unused, .mul0_neg = false, .mul1_neg = false, .acc0_src0 = lima_gp_src_unused, .acc0_src1 = lima_gp_src_unused, .acc1_src0 = lima_gp_src_unused, .acc1_src1 = lima_gp_src_unused, .acc0_src0_neg = false, .acc0_src1_neg = false, .acc1_src0_neg = false, .acc1_src1_neg = false, .load_addr = 0, .load_offset = lima_gp_load_off_none, .register0_addr = 0, .register0_attribute = false, .register1_addr = 0, .store0_temporary = false, .store1_temporary = false, .branch = false, .branch_target_lo = false, .store0_src_x = lima_gp_store_src_none, .store0_src_y = lima_gp_store_src_none, .store1_src_z = lima_gp_store_src_none, .store1_src_w = lima_gp_store_src_none, .acc_op = lima_gp_acc_op_add, .complex_op = lima_gp_complex_op_nop, .store0_addr = 0, .store0_varying = false, .store1_addr = 0, .store1_varying = false, .mul_op = lima_gp_mul_op_mul, .pass_op = lima_gp_pass_op_pass, .complex_src = lima_gp_src_unused, .pass_src = lima_gp_src_unused, .unknown_1 = 0, .branch_target = 0 }; *instr = nop_instr; if (ir_instr->mul_slots[0]) emit_mul_slot_zero(instr, ir_instr->mul_slots[0]); if (ir_instr->mul_slots[1]) emit_mul_slot_one(instr, ir_instr->mul_slots[1]); if (ir_instr->add_slots[0]) emit_add_slot_zero(instr, ir_instr->add_slots[0]); if (ir_instr->add_slots[1]) emit_add_slot_one(instr, ir_instr->add_slots[1]); if (ir_instr->uniform_slot_num_used) emit_uniform_slot(instr, ir_instr); if (ir_instr->attr_reg_slot_num_used) emit_reg_zero_slot(instr, ir_instr); if (ir_instr->reg_slot_num_used) emit_reg_one_slot(instr, ir_instr); if (ir_instr->branch_slot) emit_branch_slot(instr); unsigned i; for (i = 0; i < ir_instr->store_slot_num_used; i++) emit_store_slot(instr, ir_instr->store_slot[i]); if (ir_instr->complex_slot) emit_complex_slot(instr, ir_instr->complex_slot); if (ir_instr->pass_slot) emit_pass_slot(instr, ir_instr->pass_slot); } static bool emit_block(codegen_block_t* block, lima_gp_ir_block_t* ir_block) { block->instrs = malloc(sizeof(lima_gp_instruction_t) * ir_block->num_instrs); if (!block->instrs) return false; block->num_instrs = ir_block->num_instrs; block->has_branch = false; lima_gp_ir_instr_t* instr; unsigned i = 0; gp_ir_block_for_each_instr(ir_block, instr) { emit_instr(&block->instrs[i], instr); if (instr->branch_slot) { block->has_branch = true; lima_gp_ir_branch_node_t* branch_node = gp_ir_node_to_branch(instr->branch_slot); block->branch_dest = branch_node->dest->index; } i++; }