diff options
Diffstat (limited to 'lib/intel_alu.c')
-rw-r--r-- | lib/intel_alu.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/lib/intel_alu.c b/lib/intel_alu.c new file mode 100644 index 00000000..9e73b0e8 --- /dev/null +++ b/lib/intel_alu.c @@ -0,0 +1,207 @@ + +#include "intel_alu.h" +#include "intel_batchbuffer.h" + +struct intel_batchbuffer *batch; + +static int check_opcode(uint32_t opcode) +{ + switch(opcode) { + case NOOP: + case LOAD: + case LOADINV: + case LOAD0: + case LOAD1: + case ADD: + case SUB: + case AND: + case OR: + case XOR: + case STORE: + case STOREINV: + return 0; + default: + return 1; + } +} + +static int check_operand(uint32_t operand) +{ + switch(operand) { + case R0: + case R1: + case R2: + case R3: + case R4: + case R5: + case R6: + case R7: + case R8: + case R9: + case R10: + case R11: + case R12: + case R13: + case R14: + case R15: + case SRCA: + case SRCB: + case ACCU: + case ZF: + case CF: + return 0; + default: + return 1; + } +} + +#define R_0 0x2600 +#define R_1 0x2608 +#define R_2 0x2610 +#define R_3 0x2618 +#define R_4 0x2620 +#define R_5 0x2628 +#define R_6 0x2630 +#define R_7 0x2638 +#define R_8 0x2640 +#define R_9 0x2648 +#define R_10 0x2650 +#define R_11 0x2658 +#define R_12 0x2660 +#define R_13 0x2668 +#define R_14 0x2670 +#define R_15 0x2678 + +uint32_t gpr_reg[] = { + R_0, + R_1, + R_2, + R_3, + R_4, + R_5, + R_6, + R_7, + R_8, + R_9, + R_10, + R_11, + R_12, + R_13, + R_14, + R_15, +}; + +int intel_alu_init(int drm_fd, drm_intel_bufmgr *bufmgr) +{ + uint32_t devid; + + devid = intel_get_drm_devid(drm_fd); + if (!IS_HASWELL(devid)) + return 1; + + batch = intel_batchbuffer_alloc(bufmgr, devid); + if (!batch) + return 1; + + return 0; +} + +/* + intel_alu_load_gpr_xxx(); + + intel_alu_begin(); + intel_alu_instr(); + ... + intel_alu_end(); + + intel_alu_store_gpr(); + */ + +#define MATH_INSTR_MAX 64 /* HSW has 64 max, BDW has 256 max, in one shot */ +uint32_t instr[MATH_INSTR_MAX]; +uint32_t shot_len, shot_idx; + +int intel_alu_begin(uint32_t num) +{ + if (num > MATH_INSTR_MAX) + return 1; + + shot_len = num; + shot_idx = 0; + memset(instr, 0, sizeof(instr)); + return 0; +} + +#define MI_MATH (0x1a << 23) + +void intel_alu_end(void) +{ + int i; + + assert(shot_idx == shot_len); + + BEGIN_BATCH(shot_len + 1); + OUT_BATCH(MI_MATH | (shot_len - 1)); + for (i = 0; i < shot_len; i++) + OUT_BATCH(instr[i]); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_on_ring(batch, I915_EXEC_RENDER); +} + +void intel_alu_instr(uint32_t opcode, uint32_t operand1, uint32_t operand2) +{ + if (check_opcode(opcode)) + opcode = NOOP; + if (check_operand(operand1) || check_operand(operand2)) + opcode = NOOP; + + instr[shot_idx++] = (opcode << 20) | (operand1 << 10) | operand2; +} + +#define MI_LOAD_REGISTER_IMM ((0x22<<23) | 1) +#define MI_LOAD_REGISTER_REG ((0x2a<<23) | 1) +#define MI_LOAD_REGISTER_MEM ((0x29<<23) | 1) +#define MI_STORE_REGISTER_MEM ((0x24<<23) | 1) + +void intel_alu_load_gpr_imm(uint32_t gpr, uint32_t val) +{ + BEGIN_BATCH(4); + OUT_BATCH(MI_LOAD_REGISTER_IMM); + OUT_BATCH(gpr_reg[gpr]); + OUT_BATCH(val); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); +} + +void intel_alu_load_gpr_reg(uint32_t gpr, uint32_t reg) +{ + BEGIN_BATCH(4); + OUT_BATCH(MI_LOAD_REGISTER_REG); + OUT_BATCH(gpr_reg[gpr]); + OUT_BATCH(reg); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); +} + +void intel_alu_load_gpr_mem(uint32_t gpr, drm_intel_bo *bo, uint32_t off) +{ + BEGIN_BATCH(4); + OUT_BATCH(MI_LOAD_REGISTER_MEM); + OUT_BATCH(gpr_reg[gpr]); + OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, off); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); +} + +void intel_alu_store_gpr(uint32_t gpr, drm_intel_bo *bo, uint32_t off) +{ + BEGIN_BATCH(4); + OUT_BATCH(MI_STORE_REGISTER_MEM); + OUT_BATCH(gpr_reg[gpr]); + OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, off); + OUT_BATCH(MI_NOOP); + ADVANCE_BATCH(); + + intel_batchbuffer_flush_on_ring(batch, I915_EXEC_RENDER); +} |