static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; compiler->mode32 = 0; if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) return SLJIT_SUCCESS; /* Empty instruction. */ if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; } return emit_load_imm64(compiler, dst, srcw); } compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; compiler->mode32 = 0; return SLJIT_SUCCESS; } dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) dst_r = src; else { if (sign) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = MOVSXD_r_rm; } else { compiler->mode32 = 1; FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); compiler->mode32 = 0; } } if (dst & SLJIT_MEM) { compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; compiler->mode32 = 0; } return SLJIT_SUCCESS; }
int sljit_emit_return(struct sljit_compiler *compiler, int src, sljit_w srcw) { int size; sljit_ub *buf; CHECK_ERROR(); check_sljit_emit_return(compiler, src, srcw); SLJIT_ASSERT(compiler->args >= 0); compiler->flags_saved = 0; CHECK_EXTRA_REGS(src, srcw, (void)0); if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) FAIL_IF(emit_mov(compiler, SLJIT_RETURN_REG, 0, src, srcw)); if (compiler->local_size > 0) FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size)); size = 2 + (compiler->generals <= 3 ? compiler->generals : 3); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->args > 2) size += 2; #else if (compiler->args > 0) size += 2; #endif buf = (sljit_ub*)ensure_buf(compiler, 1 + size); FAIL_IF(!buf); INC_SIZE(size); if (compiler->generals > 0) POP_REG(reg_map[SLJIT_GENERAL_REG1]); if (compiler->generals > 1) POP_REG(reg_map[SLJIT_GENERAL_REG2]); if (compiler->generals > 2) POP_REG(reg_map[SLJIT_GENERAL_REG3]); POP_REG(reg_map[TMP_REGISTER]); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->args > 2) RETN(sizeof(sljit_w)); else RET(); #else if (compiler->args > 0) RETN(compiler->args * sizeof(sljit_w)); else RET(); #endif return SLJIT_SUCCESS; }
static void x86_emit_inst(Inst* inst, int* pc2addr, int rodata_addr) { switch (inst->op) { case MOV: emit_mov(inst->dst.reg, &inst->src); break; case ADD: if (inst->src.type == REG) { emit_1(0x01); emit_reg2(inst->dst.reg, inst->src.reg); } else { emit_2(0x81, 0xc0 + REGNO[inst->dst.reg]); emit_le(inst->src.imm); } emit_2(0x81, 0xe0 + REGNO[inst->dst.reg]); emit_le(0xffffff); break; case SUB: if (inst->src.type == REG) { emit_1(0x29); emit_reg2(inst->dst.reg, inst->src.reg); } else { emit_2(0x81, 0xe8 + REGNO[inst->dst.reg]); emit_le(inst->src.imm); } emit_2(0x81, 0xe0 + REGNO[inst->dst.reg]); emit_le(0xffffff); break; case LOAD: emit_1(0x8b); goto store_load_common; case STORE: emit_1(0x89); store_load_common: if (inst->src.type == REG) { emit_2(4 + (REGNO[inst->dst.reg] * 8), 0x86 + (REGNO[inst->src.reg] * 8)); } else { emit_1(0x86 + (REGNO[inst->dst.reg] * 8)); emit_le(inst->src.imm * 4); } break; case PUTC: // push EDI emit_1(0x57); emit_mov(EDI, &inst->src); // push EAX, ECX, EDX, EBX, EDI emit_5(0x50, 0x51, 0x52, 0x53, 0x57); emit_mov_imm(B, 1); // stdout emit_mov_reg(C, ESP); emit_mov_imm(D, 1); emit_mov_imm(A, 4); // write emit_int80(); // pop EDI, EBX, EDX, ECX, EAX emit_5(0x5f, 0x5b, 0x5a, 0x59, 0x58); // pop EDI emit_1(0x5f); break; case GETC: // push EDI emit_1(0x57); // push EAX, ECX, EDX, EBX emit_4(0x50, 0x51, 0x52, 0x53); // push 0 emit_2(0x6a, 0x00); emit_mov_imm(B, 0); // stdin emit_mov_reg(C, ESP); emit_mov_imm(D, 1); emit_mov_imm(A, 3); // read emit_int80(); // pop EDI emit_1(0x5f); emit_mov_imm(B, 0); // cmp EAX, 1 emit_3(0x83, 0xf8, 0x01); // cmovnz EDI, EBX emit_3(0x0f, 0x45, 0xfb); // pop EBX, EDX, ECX, EAX emit_4(0x5b, 0x5a, 0x59, 0x58); emit_mov_reg(inst->dst.reg, EDI); // pop EDI emit_1(0x5f); break; case EXIT: emit_mov_imm(B, 0); emit_mov_imm(A, 1); // exit emit_int80(); break; case DUMP: break; case EQ: emit_setcc(inst, 0x94); break; case NE: emit_setcc(inst, 0x95); break; case LT: emit_setcc(inst, 0x9c); break; case GT: emit_setcc(inst, 0x9f); break; case LE: emit_setcc(inst, 0x9e); break; case GE: emit_setcc(inst, 0x9d); break; case JEQ: emit_jcc(inst, 0x75, pc2addr, rodata_addr); break; case JNE: emit_jcc(inst, 0x74, pc2addr, rodata_addr); break; case JLT: emit_jcc(inst, 0x7d, pc2addr, rodata_addr); break; case JGT: emit_jcc(inst, 0x7e, pc2addr, rodata_addr); break; case JLE: emit_jcc(inst, 0x7f, pc2addr, rodata_addr); break; case JGE: emit_jcc(inst, 0x7c, pc2addr, rodata_addr); break; case JMP: emit_jcc(inst, 0, pc2addr, rodata_addr); break; default: error("oops"); } }
static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) { #define MAX_IFSN 32 #define MAX_LOOP_DEPTH 32 struct brw_instruction *if_inst[MAX_IFSN], *loop_inst[MAX_LOOP_DEPTH]; struct brw_instruction *inst0, *inst1; int i, if_insn = 0, loop_insn = 0; struct brw_compile *p = &c->func; struct brw_indirect stack_index = brw_indirect(0, 0); c->reg_index = 0; prealloc_reg(c); brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack)); for (i = 0; i < c->nr_fp_insns; i++) { struct prog_instruction *inst = &c->prog_instructions[i]; struct prog_instruction *orig_inst; if ((orig_inst = inst->Data) != 0) orig_inst->Data = current_insn(p); if (inst->CondUpdate) brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); else brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE); switch (inst->Opcode) { case WM_PIXELXY: emit_pixel_xy(c, inst); break; case WM_DELTAXY: emit_delta_xy(c, inst); break; case WM_PIXELW: emit_pixel_w(c, inst); break; case WM_LINTERP: emit_linterp(c, inst); break; case WM_PINTERP: emit_pinterp(c, inst); break; case WM_CINTERP: emit_cinterp(c, inst); break; case WM_WPOSXY: emit_wpos_xy(c, inst); break; case WM_FB_WRITE: emit_fb_write(c, inst); break; case OPCODE_ABS: emit_abs(c, inst); break; case OPCODE_ADD: emit_add(c, inst); break; case OPCODE_SUB: emit_sub(c, inst); break; case OPCODE_FRC: emit_frc(c, inst); break; case OPCODE_FLR: emit_flr(c, inst); break; case OPCODE_LRP: emit_lrp(c, inst); break; case OPCODE_INT: emit_int(c, inst); break; case OPCODE_MOV: emit_mov(c, inst); break; case OPCODE_DP3: emit_dp3(c, inst); break; case OPCODE_DP4: emit_dp4(c, inst); break; case OPCODE_XPD: emit_xpd(c, inst); break; case OPCODE_DPH: emit_dph(c, inst); break; case OPCODE_RCP: emit_rcp(c, inst); break; case OPCODE_RSQ: emit_rsq(c, inst); break; case OPCODE_SIN: emit_sin(c, inst); break; case OPCODE_COS: emit_cos(c, inst); break; case OPCODE_EX2: emit_ex2(c, inst); break; case OPCODE_LG2: emit_lg2(c, inst); break; case OPCODE_MAX: emit_max(c, inst); break; case OPCODE_MIN: emit_min(c, inst); break; case OPCODE_DDX: emit_ddx(c, inst); break; case OPCODE_DDY: emit_ddy(c, inst); break; case OPCODE_SLT: emit_slt(c, inst); break; case OPCODE_SLE: emit_sle(c, inst); break; case OPCODE_SGT: emit_sgt(c, inst); break; case OPCODE_SGE: emit_sge(c, inst); break; case OPCODE_SEQ: emit_seq(c, inst); break; case OPCODE_SNE: emit_sne(c, inst); break; case OPCODE_MUL: emit_mul(c, inst); break; case OPCODE_POW: emit_pow(c, inst); break; case OPCODE_MAD: emit_mad(c, inst); break; case OPCODE_TEX: emit_tex(c, inst); break; case OPCODE_TXB: emit_txb(c, inst); break; case OPCODE_KIL_NV: emit_kil(c); break; case OPCODE_IF: assert(if_insn < MAX_IFSN); if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8); break; case OPCODE_ELSE: if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]); break; case OPCODE_ENDIF: assert(if_insn > 0); brw_ENDIF(p, if_inst[--if_insn]); break; case OPCODE_BGNSUB: case OPCODE_ENDSUB: break; case OPCODE_CAL: brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); brw_set_access_mode(p, BRW_ALIGN_1); brw_ADD(p, deref_1ud(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16)); brw_set_access_mode(p, BRW_ALIGN_16); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(4)); orig_inst = inst->Data; orig_inst->Data = &p->store[p->nr_insn]; brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); brw_pop_insn_state(p); break; case OPCODE_RET: brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(-4)); brw_set_access_mode(p, BRW_ALIGN_1); brw_MOV(p, brw_ip_reg(), deref_1ud(stack_index, 0)); brw_set_access_mode(p, BRW_ALIGN_16); brw_pop_insn_state(p); break; case OPCODE_BGNLOOP: loop_inst[loop_insn++] = brw_DO(p, BRW_EXECUTE_8); break; case OPCODE_BRK: brw_BREAK(p); brw_set_predicate_control(p, BRW_PREDICATE_NONE); break; case OPCODE_CONT: brw_CONT(p); brw_set_predicate_control(p, BRW_PREDICATE_NONE); break; case OPCODE_ENDLOOP: loop_insn--; inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]); /* patch all the BREAK instructions from last BEGINLOOP */ while (inst0 > loop_inst[loop_insn]) { inst0--; if (inst0->header.opcode == BRW_OPCODE_BREAK) { inst0->bits3.if_else.jump_count = inst1 - inst0 + 1; inst0->bits3.if_else.pop_count = 0; } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) { inst0->bits3.if_else.jump_count = inst1 - inst0; inst0->bits3.if_else.pop_count = 0; } } break; default: _mesa_printf("unsupported IR in fragment shader %d\n", inst->Opcode); } if (inst->CondUpdate) brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); else brw_set_predicate_control(p, BRW_PREDICATE_NONE); } post_wm_emit(c); for (i = 0; i < c->fp->program.Base.NumInstructions; i++) c->fp->program.Base.Instructions[i].Data = NULL; }