summaryrefslogtreecommitdiff
path: root/lib/intel_alu.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/intel_alu.c')
-rw-r--r--lib/intel_alu.c207
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);
+}