CP_REG_RMW:
cwrite $data, [$00 + @REG_READ_ADDR], 0x0
- add $02, $addr2, 0x0042
- addhi $03, $00, $addr2
- sub $02, $02, $addr2
+ add $02, $regdata, 0x0042
+ addhi $03, $00, $regdata
+ sub $02, $02, $regdata
call #fxn00
- subhi $03, $03, $addr2
- and $02, $02, $addr2
+ subhi $03, $03, $regdata
+ and $02, $02, $regdata
or $02, $02, 0x0001
xor $02, $02, 0x0001
not $02, $02
- shl $02, $02, $addr2
- ushr $02, $02, $addr2
- ishr $02, $02, $addr2
- rot $02, $02, $addr2
- min $02, $02, $addr2
- max $02, $02, $addr2
- mul8 $02, $02, $addr2
+ shl $02, $02, $regdata
+ ushr $02, $02, $regdata
+ ishr $02, $02, $regdata
+ rot $02, $02, $regdata
+ min $02, $02, $regdata
+ max $02, $02, $regdata
+ mul8 $02, $02, $regdata
msb $02, $02
- mov $addr2, $data
+ mov $usraddr, $data
mov $data, $02
waitin
mov $01, $data
cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
mov $rem, $data
cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
- (rep)store $addr, [$02 + 0x004], 0x4
+ (rep)store $memdata, [$02 + 0x004], 0x4
waitin
mov $01, $data
nop
CP_REG_RMW:
-; Test various ALU instructions, and read/write $addr2
+; Test various ALU instructions, and read/write $regdata
cwrite $data, [$00 + @REG_READ_ADDR], 0x0
-add $02, $addr2, 0x42
-addhi $03, $00, $addr2
-sub $02, $02, $addr2
+add $02, $regdata, 0x42
+addhi $03, $00, $regdata
+sub $02, $02, $regdata
call #euclid
-subhi $03, $03, $addr2
-and $02, $02, $addr2
+subhi $03, $03, $regdata
+and $02, $02, $regdata
or $02, $02, 0x1
xor $02, $02, 0x1
not $02, $02
-shl $02, $02, $addr2
-ushr $02, $02, $addr2
-ishr $02, $02, $addr2
-rot $02, $02, $addr2
-min $02, $02, $addr2
-max $02, $02, $addr2
-mul8 $02, $02, $addr2
+shl $02, $02, $regdata
+ushr $02, $02, $regdata
+ishr $02, $02, $regdata
+rot $02, $02, $regdata
+min $02, $02, $regdata
+max $02, $02, $regdata
+mul8 $02, $02, $regdata
msb $02, $02
-mov $addr2, $data
+mov $usraddr, $data
mov $data, $02
waitin
mov $01, $data
cwrite $data, [$00 + @LOAD_STORE_HI], 0x0
mov $rem, $data
cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0
-(rep)store $addr, [$02 + 0x004], 0x4
+(rep)store $memdata, [$02 + 0x004], 0x4
waitin
mov $01, $data
OPC_SETSECURE = 0x3b, /* switch secure mode on/off */
} afuc_opc;
+/**
+ * Special GPR registers:
+ *
+ * Notes: (applicable to a6xx, double check a5xx)
+ *
+ * 0x1d:
+ * $addr: writes configure GPU reg address to read/write
+ * (does not respect CP_PROTECT)
+ * $memdata: reads from FIFO filled based on MEM_READ_DWORDS/
+ * MEM_READ_ADDR
+ * 0x1e: (note different mnemonic for src vs dst)
+ * $usraddr: writes configure GPU reg address to read/write,
+ * respecting CP_PROTECT
+ * $regdata: reads from FIFO filled based on REG_READ_DWORDS/
+ * REG_READ_ADDR
+ * 0x1f:
+ * $data: reads from from pm4 input stream
+ * $data: writes to stream configured by write to $addr
+ * or $usraddr
+ */
+typedef enum {
+ REG_REM = 0x1c,
+ REG_MEMDATA = 0x1d, /* when used as src */
+ REG_ADDR = 0x1d, /* when used as dst */
+ REG_REGDATA = 0x1e, /* when used as src */
+ REG_USRADDR = 0x1e, /* when used as dst */
+ REG_DATA = 0x1f,
+} afuc_reg;
+
typedef union PACKED {
/* addi, subi, andi, ori, xori, etc: */
struct PACKED {
long int ret;
if (!strcmp(str, "$rem"))
- return 0x1c;
+ return REG_REM;
+ else if (!strcmp(str, "$memdata"))
+ return REG_MEMDATA;
else if (!strcmp(str, "$addr"))
- return 0x1d;
- else if (!strcmp(str, "$addr2"))
- return 0x1e;
+ return REG_ADDR;
+ else if (!strcmp(str, "$regdata"))
+ return REG_REGDATA;
+ else if (!strcmp(str, "$usraddr"))
+ return REG_USRADDR;
else if (!strcmp(str, "$data"))
return 0x1f;
#define printlbl(fmt, ...) afuc_printc(AFUC_LBL, fmt, ##__VA_ARGS__)
static void
-print_reg(unsigned reg)
+print_src(unsigned reg)
{
- // XXX seems like *reading* $00 --> literal zero??
- // seems like read from $1c gives packet remaining len??
- // $01 current packet header, writing to $01 triggers
- // parsing header and jumping to appropriate handler.
- if (reg == 0x1c)
+ if (reg == REG_REM)
printf("$rem"); /* remainding dwords in packet */
- else if (reg == 0x1d)
- printf("$addr");
- else if (reg == 0x1e)
- printf("$addr2"); // XXX
- else if (reg == 0x1f)
+ else if (reg == REG_MEMDATA)
+ printf("$memdata");
+ else if (reg == REG_REGDATA)
+ printf("$regdata");
+ else if (reg == REG_DATA)
printf("$data");
else
printf("$%02x", reg);
}
static void
-print_src(unsigned reg)
-{
- print_reg(reg);
-}
-
-static void
print_dst(unsigned reg)
{
- print_reg(reg);
+ if (reg == REG_REM)
+ printf("$rem"); /* remainding dwords in packet */
+ else if (reg == REG_ADDR)
+ printf("$addr");
+ else if (reg == REG_USRADDR)
+ printf("$usraddr");
+ else if (reg == REG_DATA)
+ printf("$data");
+ else
+ printf("$%02x", reg);
}
static void
printf("(rep)");
bool is_control_reg = true;
+ bool is_store = true;
if (gpuver >= 6) {
switch (opc) {
case OPC_CWRITE6:
printf("cwrite ");
break;
case OPC_CREAD6:
+ is_store = false;
printf("cread ");
break;
case OPC_STORE6:
break;
case OPC_LOAD6:
is_control_reg = false;
+ is_store = false;
printf("load ");
break;
default:
printf("cwrite ");
break;
case OPC_CREAD5:
+ is_store = false;
printf("cread ");
break;
default:
}
}
- print_src(instr->control.src1);
+ if (is_store)
+ print_src(instr->control.src1);
+ else
+ print_dst(instr->control.src1);
printf(", [");
print_src(instr->control.src2);
printf(" + ");