1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2017 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker #ifndef _AFUC_H_
7*61046927SAndroid Build Coastguard Worker #define _AFUC_H_
8*61046927SAndroid Build Coastguard Worker
9*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
10*61046927SAndroid Build Coastguard Worker
11*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
12*61046927SAndroid Build Coastguard Worker
13*61046927SAndroid Build Coastguard Worker /*
14*61046927SAndroid Build Coastguard Worker TODO kernel debugfs to inject packet into rb for easier experimentation. It
15*61046927SAndroid Build Coastguard Worker should trigger reloading pfp/me and resetting gpu..
16*61046927SAndroid Build Coastguard Worker
17*61046927SAndroid Build Coastguard Worker Actually maybe it should be flag on submit ioctl to be able to deal w/ relocs,
18*61046927SAndroid Build Coastguard Worker should be restricted to CAP_ADMIN and probably compile option too (default=n).
19*61046927SAndroid Build Coastguard Worker if flag set, copy cmdstream bo contents into RB instead of IB'ing to it from
20*61046927SAndroid Build Coastguard Worker RB.
21*61046927SAndroid Build Coastguard Worker */
22*61046927SAndroid Build Coastguard Worker
23*61046927SAndroid Build Coastguard Worker typedef enum {
24*61046927SAndroid Build Coastguard Worker OPC_NOP,
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Worker #define ALU(name) \
27*61046927SAndroid Build Coastguard Worker OPC_##name, \
28*61046927SAndroid Build Coastguard Worker OPC_##name##I,
29*61046927SAndroid Build Coastguard Worker ALU(ADD) /* add immediate */
30*61046927SAndroid Build Coastguard Worker ALU(ADDHI) /* add immediate (hi 32b of 64b) */
31*61046927SAndroid Build Coastguard Worker ALU(SUB) /* subtract immediate */
32*61046927SAndroid Build Coastguard Worker ALU(SUBHI) /* subtract immediate (hi 32b of 64b) */
33*61046927SAndroid Build Coastguard Worker ALU(AND) /* AND immediate */
34*61046927SAndroid Build Coastguard Worker ALU(OR) /* OR immediate */
35*61046927SAndroid Build Coastguard Worker ALU(XOR) /* XOR immediate */
36*61046927SAndroid Build Coastguard Worker ALU(NOT) /* bitwise not of immed (src1 ignored) */
37*61046927SAndroid Build Coastguard Worker ALU(SHL) /* shift-left immediate */
38*61046927SAndroid Build Coastguard Worker ALU(USHR) /* unsigned shift right by immediate */
39*61046927SAndroid Build Coastguard Worker ALU(ISHR) /* signed shift right by immediate */
40*61046927SAndroid Build Coastguard Worker ALU(ROT) /* rotate left (left shift with wrap-around) */
41*61046927SAndroid Build Coastguard Worker ALU(MUL8) /* 8bit multiply by immediate */
42*61046927SAndroid Build Coastguard Worker ALU(MIN)
43*61046927SAndroid Build Coastguard Worker ALU(MAX)
44*61046927SAndroid Build Coastguard Worker ALU(CMP) /* compare src to immed */
45*61046927SAndroid Build Coastguard Worker ALU(BIC) /* AND with second source negated */
46*61046927SAndroid Build Coastguard Worker OPC_SETBIT, /* Set or clear a bit dynamically */
47*61046927SAndroid Build Coastguard Worker OPC_MOVI, /* move immediate */
48*61046927SAndroid Build Coastguard Worker OPC_SETBITI, /* Set a bit */
49*61046927SAndroid Build Coastguard Worker OPC_CLRBIT, /* Clear a bit */
50*61046927SAndroid Build Coastguard Worker OPC_UBFX, /* Unsigned BitField eXtract */
51*61046927SAndroid Build Coastguard Worker OPC_BFI, /* BitField Insert */
52*61046927SAndroid Build Coastguard Worker #undef ALU
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker /* Return the most-significant bit of src2, or 0 if src2 == 0 (the
55*61046927SAndroid Build Coastguard Worker * same as if src2 == 1). src1 is ignored. Note that this overlaps
56*61046927SAndroid Build Coastguard Worker * with STORE, so it can only be used with the two-source encoding.
57*61046927SAndroid Build Coastguard Worker */
58*61046927SAndroid Build Coastguard Worker OPC_MSB,
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker /* These seem something to do with setting some external state..
61*61046927SAndroid Build Coastguard Worker * doesn't seem to map *directly* to registers, but I guess that
62*61046927SAndroid Build Coastguard Worker * is where things end up. For example, this sequence in the
63*61046927SAndroid Build Coastguard Worker * CP_INDIRECT_BUFFER handler:
64*61046927SAndroid Build Coastguard Worker *
65*61046927SAndroid Build Coastguard Worker * mov $02, $data ; low 32b of IB target address
66*61046927SAndroid Build Coastguard Worker * mov $03, $data ; high 32b of IB target
67*61046927SAndroid Build Coastguard Worker * mov $04, $data ; IB size in dwords
68*61046927SAndroid Build Coastguard Worker * breq $04, 0x0, #l23 (#69, 04a2)
69*61046927SAndroid Build Coastguard Worker * and $05, $18, 0x0003
70*61046927SAndroid Build Coastguard Worker * shl $05, $05, 0x0002
71*61046927SAndroid Build Coastguard Worker * cwrite $02, [$05 + 0x0b0], 0x8
72*61046927SAndroid Build Coastguard Worker * cwrite $03, [$05 + 0x0b1], 0x8
73*61046927SAndroid Build Coastguard Worker * cwrite $04, [$05 + 0x0b2], 0x8
74*61046927SAndroid Build Coastguard Worker *
75*61046927SAndroid Build Coastguard Worker * Note that CP_IB1/2_BASE_LO/HI/BUFSZ in 0x0b1f->0xb21 (IB1) and
76*61046927SAndroid Build Coastguard Worker * 0x0b22->0x0b24 (IB2). Presumably $05 ends up w/ different value
77*61046927SAndroid Build Coastguard Worker * for RB->IB1 vs IB1->IB2.
78*61046927SAndroid Build Coastguard Worker */
79*61046927SAndroid Build Coastguard Worker OPC_CWRITE,
80*61046927SAndroid Build Coastguard Worker OPC_CREAD,
81*61046927SAndroid Build Coastguard Worker
82*61046927SAndroid Build Coastguard Worker /* A6xx added new opcodes that let you read/write directly to memory (and
83*61046927SAndroid Build Coastguard Worker * bypass the IOMMU?).
84*61046927SAndroid Build Coastguard Worker */
85*61046927SAndroid Build Coastguard Worker OPC_STORE,
86*61046927SAndroid Build Coastguard Worker OPC_LOAD,
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker /* A6xx added new opcodes that let you read/write the state of the
89*61046927SAndroid Build Coastguard Worker * SQE processor itself, like the call stack. This is mostly used by
90*61046927SAndroid Build Coastguard Worker * preemption but is also used to set the preempt routine entrypoint.
91*61046927SAndroid Build Coastguard Worker */
92*61046927SAndroid Build Coastguard Worker OPC_SREAD,
93*61046927SAndroid Build Coastguard Worker OPC_SWRITE,
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker OPC_BRNEI, /* relative branch (if $src != immed) */
96*61046927SAndroid Build Coastguard Worker OPC_BREQI, /* relative branch (if $src == immed) */
97*61046927SAndroid Build Coastguard Worker OPC_BRNEB, /* relative branch (if bit not set) */
98*61046927SAndroid Build Coastguard Worker OPC_BREQB, /* relative branch (if bit is set) */
99*61046927SAndroid Build Coastguard Worker OPC_RET, /* return */
100*61046927SAndroid Build Coastguard Worker OPC_IRET, /* return from preemption interrupt handler */
101*61046927SAndroid Build Coastguard Worker OPC_CALL, /* "function" call */
102*61046927SAndroid Build Coastguard Worker OPC_WAITIN, /* wait for input (ie. wait for WPTR to advance) */
103*61046927SAndroid Build Coastguard Worker OPC_BL, /* Branch and Link (same as the MIPS/ARM instruction) */
104*61046927SAndroid Build Coastguard Worker OPC_SETSECURE, /* switch secure mode on/off */
105*61046927SAndroid Build Coastguard Worker OPC_JUMPR, /* indirect jump with a register offset */
106*61046927SAndroid Build Coastguard Worker OPC_SRET, /* Return instruction to use with "bl" */
107*61046927SAndroid Build Coastguard Worker OPC_JUMPA, /* Absolute jump instruction */
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker /* pseudo-opcodes without an actual encoding */
110*61046927SAndroid Build Coastguard Worker OPC_BREQ,
111*61046927SAndroid Build Coastguard Worker OPC_BRNE,
112*61046927SAndroid Build Coastguard Worker OPC_JUMP,
113*61046927SAndroid Build Coastguard Worker OPC_RAW_LITERAL,
114*61046927SAndroid Build Coastguard Worker OPC_JUMPTBL,
115*61046927SAndroid Build Coastguard Worker } afuc_opc;
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker /**
118*61046927SAndroid Build Coastguard Worker * Special GPR registers:
119*61046927SAndroid Build Coastguard Worker *
120*61046927SAndroid Build Coastguard Worker * Notes: (applicable to a6xx, double check a5xx)
121*61046927SAndroid Build Coastguard Worker *
122*61046927SAndroid Build Coastguard Worker * 0x1a:
123*61046927SAndroid Build Coastguard Worker * $sp
124*61046927SAndroid Build Coastguard Worker * 0x1b:
125*61046927SAndroid Build Coastguard Worker * $lr: written by bl
126*61046927SAndroid Build Coastguard Worker * 0x1d:
127*61046927SAndroid Build Coastguard Worker * $addr: writes configure GPU reg address to read/write
128*61046927SAndroid Build Coastguard Worker * (does not respect CP_PROTECT)
129*61046927SAndroid Build Coastguard Worker * $memdata: reads from FIFO filled based on MEM_READ_DWORDS/
130*61046927SAndroid Build Coastguard Worker * MEM_READ_ADDR
131*61046927SAndroid Build Coastguard Worker * 0x1e: (note different mnemonic for src vs dst)
132*61046927SAndroid Build Coastguard Worker * $usraddr: writes configure GPU reg address to read/write,
133*61046927SAndroid Build Coastguard Worker * respecting CP_PROTECT
134*61046927SAndroid Build Coastguard Worker * $regdata: reads from FIFO filled based on REG_READ_DWORDS/
135*61046927SAndroid Build Coastguard Worker * REG_READ_ADDR
136*61046927SAndroid Build Coastguard Worker * 0x1f:
137*61046927SAndroid Build Coastguard Worker * $data: reads from from pm4 input stream
138*61046927SAndroid Build Coastguard Worker * $data: writes to stream configured by write to $addr
139*61046927SAndroid Build Coastguard Worker * or $usraddr
140*61046927SAndroid Build Coastguard Worker */
141*61046927SAndroid Build Coastguard Worker typedef enum {
142*61046927SAndroid Build Coastguard Worker REG_SP = 0x1a,
143*61046927SAndroid Build Coastguard Worker REG_LR = 0x1b,
144*61046927SAndroid Build Coastguard Worker REG_REM = 0x1c,
145*61046927SAndroid Build Coastguard Worker REG_MEMDATA = 0x1d, /* when used as src */
146*61046927SAndroid Build Coastguard Worker REG_ADDR = 0x1d, /* when used as dst */
147*61046927SAndroid Build Coastguard Worker REG_REGDATA = 0x1e, /* when used as src */
148*61046927SAndroid Build Coastguard Worker REG_USRADDR = 0x1e, /* when used as dst */
149*61046927SAndroid Build Coastguard Worker REG_DATA = 0x1f,
150*61046927SAndroid Build Coastguard Worker } afuc_reg;
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker struct afuc_instr {
153*61046927SAndroid Build Coastguard Worker afuc_opc opc;
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker uint8_t dst;
156*61046927SAndroid Build Coastguard Worker uint8_t src1;
157*61046927SAndroid Build Coastguard Worker uint8_t src2;
158*61046927SAndroid Build Coastguard Worker uint32_t immed;
159*61046927SAndroid Build Coastguard Worker uint8_t shift;
160*61046927SAndroid Build Coastguard Worker uint8_t bit;
161*61046927SAndroid Build Coastguard Worker uint8_t xmov;
162*61046927SAndroid Build Coastguard Worker uint8_t sds;
163*61046927SAndroid Build Coastguard Worker uint32_t literal;
164*61046927SAndroid Build Coastguard Worker int offset;
165*61046927SAndroid Build Coastguard Worker const char *label;
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker bool has_immed : 1;
168*61046927SAndroid Build Coastguard Worker bool has_shift : 1;
169*61046927SAndroid Build Coastguard Worker bool has_bit : 1;
170*61046927SAndroid Build Coastguard Worker bool is_literal : 1;
171*61046927SAndroid Build Coastguard Worker bool rep : 1;
172*61046927SAndroid Build Coastguard Worker bool preincrement : 1;
173*61046927SAndroid Build Coastguard Worker bool peek : 1;
174*61046927SAndroid Build Coastguard Worker };
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker /* Literal offsets are sometimes encoded as NOP instructions, which on a6xx+
177*61046927SAndroid Build Coastguard Worker * must have a high 8 bits of 0x01.
178*61046927SAndroid Build Coastguard Worker */
179*61046927SAndroid Build Coastguard Worker static inline uint32_t
afuc_nop_literal(uint32_t x,unsigned gpuver)180*61046927SAndroid Build Coastguard Worker afuc_nop_literal(uint32_t x, unsigned gpuver)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker assert((x >> 24) == 0);
183*61046927SAndroid Build Coastguard Worker return gpuver < 6 ? x : x | (1 << 24);
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Worker void print_control_reg(uint32_t id);
187*61046927SAndroid Build Coastguard Worker void print_sqe_reg(uint32_t id);
188*61046927SAndroid Build Coastguard Worker void print_pipe_reg(uint32_t id);
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker #endif /* _AFUC_H_ */
191