1; Copyright (c) 2020 Valve Corporation 2; 3; Permission is hereby granted, free of charge, to any person obtaining a 4; copy of this software and associated documentation files (the "Software"), 5; to deal in the Software without restriction, including without limitation 6; the rights to use, copy, modify, merge, publish, distribute, sublicense, 7; and/or sell copies of the Software, and to permit persons to whom the 8; Software is furnished to do so, subject to the following conditions: 9; 10; The above copyright notice and this permission notice (including the next 11; paragraph) shall be included in all copies or substantial portions of the 12; Software. 13; 14; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20; SOFTWARE. 21; 22; 23; This file is the source for a simple mock firmware used to regression test 24; the afuc assembler/disassembler. Note, it won't actually work if you try to 25; load it on the GPU! First this is assembled, compared to the reference 26; binary, then disassambled and compared to the reference disassembly. We do 27; this to avoid having to host the actual firmware, especially the disassembled 28; version, in Mesa. 29[01000001] 30[01000000] 31loc02: 32mov $02, 0x883 33mov $03, 0xbeef 34mov $04, 0xdead << 16 35or $03, $03, $04 36cwrite $02, [$00 + @REG_WRITE_ADDR], 0x0 37cwrite $03, [$00 + @REG_WRITE], 0x0 38waitin 39mov $01, $data 40 41CP_ME_INIT: 42; test label-as-immediate feature 43mov $02, #loc02 ; should be 0x0002 44waitin 45mov $01, $data 46 47CP_MEM_WRITE: 48; test $addr + (rep) + (xmovN) with ALU 49mov $addr, 0xa0 << 24 50mov $02, 4 51(xmov1)add $data, $02, $data 52mov $addr, 0xa204 << 16 53(rep)(xmov3)mov $data, $data 54waitin 55mov $01, $data 56 57CP_SCRATCH_WRITE: 58; test (rep) + flags + non-zero offset with cwrite 59; TODO: 0x4 flag is actually pre-increment addressing, handle it as such 60mov $02, 0xff 61(rep)cwrite $data, [$02 + 0x001], 0x4 62waitin 63mov $01, $data 64 65CP_SET_SECURE_MODE: 66; test setsecure 67mov $02, $data 68setsecure $02, #setsecure_success 69err: 70jump #err 71nop 72setsecure_success: 73waitin 74mov $01, $data 75 76euclid: 77; Euclid's algorithm in afuc: https://en.wikipedia.org/wiki/Euclidean_algorithm 78; Since afuc doesn't do modulo, we implement the subtraction-based version. 79; 80; Demonstrates/tests comparisons and conditional branches. This also 81; demonstrates the common trick of branching in a delay slot. Note that if a 82; branch is taken and its delay slot includes another branch, the second 83; branch cannot also be taken, which is why the last branch in the sequence 84; cannot be unconditional. 85; 86; Inputs are in $02 and $03, and output is in $02. 87cmp $04, $02, $03 88breq $04, b0, #euclid_exit 89brne $04, b1, #euclid_gt 90breq $04, b2, #euclid 91sub $03, $03, $02 92euclid_gt: 93jump #euclid 94sub $02, $02, $03 95euclid_exit: 96ret 97nop 98 99CP_REG_RMW: 100; Test various ALU instructions, and read/write $addr2 101cwrite $data, [$00 + @REG_READ_ADDR], 0x0 102add $02, $addr2, 0x42 103addhi $03, $00, $addr2 104sub $02, $02, $addr2 105call #euclid 106subhi $03, $03, $addr2 107and $02, $02, $addr2 108or $02, $02, 0x1 109xor $02, $02, 0x1 110not $02, $02 111shl $02, $02, $addr2 112ushr $02, $02, $addr2 113ishr $02, $02, $addr2 114rot $02, $02, $addr2 115min $02, $02, $addr2 116max $02, $02, $addr2 117mul8 $02, $02, $addr2 118msb $02, $02 119mov $addr2, $data 120mov $data, $02 121waitin 122mov $01, $data 123 124CP_MEMCPY: 125; implement CP_MEMCPY using load/store instructions 126mov $02, $data 127mov $03, $data 128mov $04, $data 129mov $05, $data 130mov $06, $data 131cpy_header: 132breq $06, 0, #cpy_exit 133cwrite $03, [$00 + @LOAD_STORE_HI], 0x0 134load $07, [$02 + 0x004], 0x4 135cwrite $05, [$00 + @LOAD_STORE_HI], 0x0 136jump #cpy_header 137store $07, [$04 + 0x004], 0x4 138cpy_exit: 139waitin 140mov $01, $data 141 142CP_MEM_TO_MEM: 143; implement CP_MEMCPY using mem read control regs 144; tests @FOO+0x1 for 64-bit control regs, and reading/writing $rem 145cwrite $data, [$00 + @MEM_READ_ADDR], 0x0 146cwrite $data, [$00 + @MEM_READ_ADDR+1], 0x0 147mov $02, $data 148cwrite $data, [$00 + @LOAD_STORE_HI], 0x0 149mov $rem, $data 150cwrite $rem, [$00 + @MEM_READ_DWORDS], 0x0 151(rep)store $addr, [$02 + 0x004], 0x4 152waitin 153mov $01, $data 154 155UNKN15: 156; test preemptleave + iret + conditional branch w/ immed 157cread $02, [$00 + 0x101], 0x0 158brne $02, 0x0001, #exit_iret 159nop 160preemptleave #err 161nop 162nop 163nop 164waitin 165mov $01, $data 166exit_iret: 167iret 168nop 169 170UNKN0: 171UNKN1: 172UNKN2: 173UNKN3: 174PKT4: 175UNKN5: 176UNKN6: 177UNKN7: 178UNKN8: 179UNKN9: 180UNKN10: 181UNKN11: 182UNKN12: 183UNKN13: 184UNKN14: 185CP_NOP: 186CP_RECORD_PFP_TIMESTAMP: 187CP_WAIT_MEM_WRITES: 188CP_WAIT_FOR_ME: 189CP_WAIT_MEM_GTE: 190UNKN21: 191UNKN22: 192UNKN23: 193UNKN24: 194CP_DRAW_PRED_ENABLE_GLOBAL: 195CP_DRAW_PRED_ENABLE_LOCAL: 196UNKN27: 197CP_PREEMPT_ENABLE: 198CP_SKIP_IB2_ENABLE_GLOBAL: 199CP_PREEMPT_TOKEN: 200UNKN31: 201UNKN32: 202CP_DRAW_INDX: 203CP_SKIP_IB2_ENABLE_LOCAL: 204CP_DRAW_AUTO: 205CP_SET_STATE: 206CP_WAIT_FOR_IDLE: 207CP_IM_LOAD: 208CP_DRAW_INDIRECT: 209CP_DRAW_INDX_INDIRECT: 210CP_DRAW_INDIRECT_MULTI: 211CP_IM_LOAD_IMMEDIATE: 212CP_BLIT: 213CP_SET_CONSTANT: 214CP_SET_BIN_DATA5_OFFSET: 215CP_SET_BIN_DATA5: 216UNKN48: 217CP_RUN_OPENCL: 218CP_LOAD_STATE6_GEOM: 219CP_EXEC_CS: 220CP_LOAD_STATE6_FRAG: 221CP_SET_SUBDRAW_SIZE: 222CP_LOAD_STATE6: 223CP_INDIRECT_BUFFER_PFD: 224CP_DRAW_INDX_OFFSET: 225CP_REG_TEST: 226CP_COND_INDIRECT_BUFFER_PFE: 227CP_INVALIDATE_STATE: 228CP_WAIT_REG_MEM: 229CP_REG_TO_MEM: 230CP_INDIRECT_BUFFER: 231CP_INTERRUPT: 232CP_EXEC_CS_INDIRECT: 233CP_MEM_TO_REG: 234CP_SET_DRAW_STATE: 235CP_COND_EXEC: 236CP_COND_WRITE5: 237CP_EVENT_WRITE: 238CP_COND_REG_EXEC: 239UNKN73: 240CP_REG_TO_SCRATCH: 241CP_SET_DRAW_INIT_FLAGS: 242CP_SCRATCH_TO_REG: 243CP_DRAW_PRED_SET: 244CP_MEM_WRITE_CNTR: 245UNKN80: 246CP_SET_BIN_SELECT: 247CP_WAIT_REG_EQ: 248CP_SMMU_TABLE_UPDATE: 249UNKN84: 250CP_SET_CTXSWITCH_IB: 251CP_SET_PSEUDO_REG: 252CP_INDIRECT_BUFFER_CHAIN: 253CP_EVENT_WRITE_SHD: 254CP_EVENT_WRITE_CFL: 255UNKN90: 256CP_EVENT_WRITE_ZPD: 257CP_CONTEXT_REG_BUNCH: 258CP_WAIT_IB_PFD_COMPLETE: 259CP_CONTEXT_UPDATE: 260CP_SET_PROTECTED_MODE: 261UNKN96: 262UNKN97: 263UNKN98: 264CP_SET_MODE: 265CP_SET_VISIBILITY_OVERRIDE: 266CP_SET_MARKER: 267UNKN103: 268UNKN104: 269UNKN105: 270UNKN106: 271UNKN107: 272UNKN108: 273CP_REG_WRITE: 274UNKN110: 275CP_BOOTSTRAP_UCODE: 276CP_WAIT_TWO_REGS: 277CP_TEST_TWO_MEMS: 278CP_REG_TO_MEM_OFFSET_REG: 279CP_REG_TO_MEM_OFFSET_MEM: 280UNKN118: 281UNKN119: 282CP_REG_WR_NO_CTXT: 283UNKN121: 284UNKN122: 285UNKN123: 286UNKN124: 287UNKN125: 288UNKN126: 289UNKN127: 290 waitin 291 mov $01, $data 292