diff --git a/src/app/ring_stream_read.c b/src/app/ring_stream_read.c
index 90f5056dd58ef4dd1098ff630db503d6da03b354..9447e8e31e0a85116955732771d105650e522f3d 100644
--- a/src/app/ring_stream_read.c
+++ b/src/app/ring_stream_read.c
@@ -211,7 +211,7 @@ static void add_data(struct umr_stream_decode_ui *ui, struct umr_asic *asic, uin
 	fprintf(data->stack[data->sp].f, "Data block from %"PRIu32"@[0x%"PRIx64" + 0x%"PRIx64"] at %"PRIu32"@0x%"PRIx64", type %d, ", ib_vmid, data->stack[data->sp-1].ib_addr, ib_addr - data->stack[data->sp-1].ib_addr, buf_vmid, buf_addr, type);
 
 	if (type == UMR_DATABLOCK_MQD_VI || type == UMR_DATABLOCK_MQD_NV) {
-		static const char *selnames[] = { "compute", "reserved", "sdma0", "sdma1", "gfx" };
+		static const char *selnames[] = { "compute", "reserved", "sdma0", "sdma1", "gfx", "mes" };
 		enum umr_mqd_engine_sel eng;
 		uint32_t mqd[512], x;
 
@@ -221,6 +221,7 @@ static void add_data(struct umr_stream_decode_ui *ui, struct umr_asic *asic, uin
 			case 2:
 			case 3: eng = UMR_MQD_ENGINE_SDMA0; break;
 			case 4: eng = UMR_MQD_ENGINE_GFX; break;
+			case 5: eng = UMR_MQD_ENGINE_MES; break;
 			default:
 				eng = UMR_MQD_ENGINE_INVALID; break;
 		}
@@ -454,6 +455,8 @@ void umr_read_ring_stream(struct umr_asic *asic, char *ringpath)
 		enable_decoder = 3;
 	} else if (sscanf(ringpath, "2/%"SCNx32"@0x%"SCNx64".%"SCNx32, &vmid, &addr, &nwords) == 3) {
 		enable_decoder = 2;
+	} else if (sscanf(ringpath, "1/%"SCNx32"@0x%"SCNx64".%"SCNx32, &vmid, &addr, &nwords) == 3) {
+		enable_decoder = 1;
 	} else if (sscanf(ringpath, "6/%s", fname) == 1) {
 		enable_decoder = 6;
 	} else if (sscanf(ringpath, "5/%s", fname) == 1) {
diff --git a/src/lib/mqd_decode.c b/src/lib/mqd_decode.c
index bfa8a67a2d2773c9020cbe8e1bd042c4e6d12d70..a349198efef4b53616fd78b69f47f77facaec642 100644
--- a/src/lib/mqd_decode.c
+++ b/src/lib/mqd_decode.c
@@ -24,6 +24,1167 @@
  */
 #include "umr.h"
 
+static const struct umr_mqd_fields  umr_mqd_graphics_gfx12[] = {
+	{ 0, "shadow_base_lo" },
+	{ 1, "shadow_base_hi" },
+	{ 2, "reserved_2" },
+	{ 3, "reserved_3" },
+	{ 4, "fw_work_area_base_lo" },
+	{ 5, "fw_work_area_base_hi" },
+	{ 6, "shadow_initialized" },
+	{ 7, "ib_vmid" },
+	{ 8, "reserved_8" },
+	{ 9, "reserved_9" },
+	{ 10, "reserved_10" },
+	{ 11, "reserved_11" },
+	{ 12, "reserved_12" },
+	{ 13, "reserved_13" },
+	{ 14, "reserved_14" },
+	{ 15, "reserved_15" },
+	{ 16, "reserved_16" },
+	{ 17, "reserved_17" },
+	{ 18, "reserved_18" },
+	{ 19, "reserved_19" },
+	{ 20, "reserved_20" },
+	{ 21, "reserved_21" },
+	{ 22, "reserved_22" },
+	{ 23, "reserved_23" },
+	{ 24, "reserved_24" },
+	{ 25, "reserved_25" },
+	{ 26, "reserved_26" },
+	{ 27, "reserved_27" },
+	{ 28, "reserved_28" },
+	{ 29, "reserved_29" },
+	{ 30, "reserved_30" },
+	{ 31, "reserved_31" },
+	{ 32, "reserved_32" },
+	{ 33, "reserved_33" },
+	{ 34, "reserved_34" },
+	{ 35, "reserved_35" },
+	{ 36, "reserved_36" },
+	{ 37, "reserved_37" },
+	{ 38, "reserved_38" },
+	{ 39, "reserved_39" },
+	{ 40, "reserved_40" },
+	{ 41, "reserved_41" },
+	{ 42, "reserved_42" },
+	{ 43, "reserved_43" },
+	{ 44, "reserved_44" },
+	{ 45, "reserved_45" },
+	{ 46, "reserved_46" },
+	{ 47, "reserved_47" },
+	{ 48, "reserved_48" },
+	{ 49, "reserved_49" },
+	{ 50, "reserved_50" },
+	{ 51, "reserved_51" },
+	{ 52, "reserved_52" },
+	{ 53, "reserved_53" },
+	{ 54, "reserved_54" },
+	{ 55, "reserved_55" },
+	{ 56, "reserved_56" },
+	{ 57, "reserved_57" },
+	{ 58, "reserved_58" },
+	{ 59, "reserved_59" },
+	{ 60, "reserved_60" },
+	{ 61, "reserved_61" },
+	{ 62, "reserved_62" },
+	{ 63, "reserved_63" },
+	{ 64, "reserved_64" },
+	{ 65, "reserved_65" },
+	{ 66, "reserved_66" },
+	{ 67, "reserved_67" },
+	{ 68, "reserved_68" },
+	{ 69, "reserved_69" },
+	{ 70, "reserved_70" },
+	{ 71, "reserved_71" },
+	{ 72, "reserved_72" },
+	{ 73, "reserved_73" },
+	{ 74, "reserved_74" },
+	{ 75, "reserved_75" },
+	{ 76, "reserved_76" },
+	{ 77, "reserved_77" },
+	{ 78, "reserved_78" },
+	{ 79, "reserved_79" },
+	{ 80, "reserved_80" },
+	{ 81, "reserved_81" },
+	{ 82, "reserved_82" },
+	{ 83, "reserved_83" },
+	{ 84, "checksum_lo" },
+	{ 85, "checksum_hi" },
+	{ 86, "cp_mqd_query_time_lo" },
+	{ 87, "cp_mqd_query_time_hi" },
+	{ 88, "reserved_88" },
+	{ 89, "reserved_89" },
+	{ 90, "reserved_90" },
+	{ 91, "reserved_91" },
+	{ 92, "cp_mqd_query_wave_count" },
+	{ 93, "cp_mqd_query_gfx_hqd_rptr" },
+	{ 94, "cp_mqd_query_gfx_hqd_wptr" },
+	{ 95, "cp_mqd_query_gfx_hqd_offset" },
+	{ 96, "reserved_96" },
+	{ 97, "reserved_97" },
+	{ 98, "reserved_98" },
+	{ 99, "reserved_99" },
+	{ 100, "reserved_100" },
+	{ 101, "reserved_101" },
+	{ 102, "reserved_102" },
+	{ 103, "reserved_103" },
+	{ 104, "task_shader_control_buf_addr_lo" },
+	{ 105, "task_shader_control_buf_addr_hi" },
+	{ 106, "task_shader_read_rptr_lo" },
+	{ 107, "task_shader_read_rptr_hi" },
+	{ 108, "task_shader_num_entries" },
+	{ 109, "task_shader_num_entries_bits" },
+	{ 110, "task_shader_ring_buffer_addr_lo" },
+	{ 111, "task_shader_ring_buffer_addr_hi" },
+	{ 112, "reserved_112" },
+	{ 113, "reserved_113" },
+	{ 114, "reserved_114" },
+	{ 115, "reserved_115" },
+	{ 116, "reserved_116" },
+	{ 117, "reserved_117" },
+	{ 118, "reserved_118" },
+	{ 119, "reserved_119" },
+	{ 120, "reserved_120" },
+	{ 121, "reserved_121" },
+	{ 122, "reserved_122" },
+	{ 123, "reserved_123" },
+	{ 124, "reserved_124" },
+	{ 125, "reserved_125" },
+	{ 126, "reserved_126" },
+	{ 127, "reserved_127" },
+	{ 128, "cp_mqd_base_addr" },
+	{ 129, "cp_mqd_base_addr_hi" },
+	{ 130, "cp_gfx_hqd_active" },
+	{ 131, "cp_gfx_hqd_vmid" },
+	{ 132, "reserved_132" },
+	{ 133, "reserved_133" },
+	{ 134, "cp_gfx_hqd_queue_priority" },
+	{ 135, "cp_gfx_hqd_quantum" },
+	{ 136, "cp_gfx_hqd_base" },
+	{ 137, "cp_gfx_hqd_base_hi" },
+	{ 138, "cp_gfx_hqd_rptr" },
+	{ 139, "cp_gfx_hqd_rptr_addr" },
+	{ 140, "cp_gfx_hqd_rptr_addr_hi" },
+	{ 141, "cp_rb_wptr_poll_addr_lo" },
+	{ 142, "cp_rb_wptr_poll_addr_hi" },
+	{ 143, "cp_rb_doorbell_control" },
+	{ 144, "cp_gfx_hqd_offset" },
+	{ 145, "cp_gfx_hqd_cntl" },
+	{ 146, "reserved_146" },
+	{ 147, "reserved_147" },
+	{ 148, "cp_gfx_hqd_csmd_rptr" },
+	{ 149, "cp_gfx_hqd_wptr" },
+	{ 150, "cp_gfx_hqd_wptr_hi" },
+	{ 151, "reserved_151" },
+	{ 152, "reserved_152" },
+	{ 153, "reserved_153" },
+	{ 154, "reserved_154" },
+	{ 155, "reserved_155" },
+	{ 156, "cp_gfx_hqd_mapped" },
+	{ 157, "cp_gfx_hqd_que_mgr_control" },
+	{ 158, "reserved_158" },
+	{ 159, "reserved_159" },
+	{ 160, "cp_gfx_hqd_hq_status0" },
+	{ 161, "cp_gfx_hqd_hq_control0" },
+	{ 162, "cp_gfx_mqd_control" },
+	{ 163, "reserved_163" },
+	{ 164, "reserved_164" },
+	{ 165, "reserved_165" },
+	{ 166, "reserved_166" },
+	{ 167, "reserved_167" },
+	{ 168, "reserved_168" },
+	{ 169, "reserved_169" },
+	{ 170, "reserved_170" },
+	{ 171, "reserved_171" },
+	{ 172, "reserved_172" },
+	{ 173, "reserved_173" },
+	{ 174, "reserved_174" },
+	{ 175, "reserved_175" },
+	{ 176, "reserved_176" },
+	{ 177, "reserved_177" },
+	{ 178, "reserved_178" },
+	{ 179, "reserved_179" },
+	{ 180, "reserved_180" },
+	{ 181, "reserved_181" },
+	{ 182, "reserved_182" },
+	{ 183, "reserved_183" },
+	{ 184, "reserved_184" },
+	{ 185, "reserved_185" },
+	{ 186, "reserved_186" },
+	{ 187, "reserved_187" },
+	{ 188, "reserved_188" },
+	{ 189, "reserved_189" },
+	{ 190, "reserved_190" },
+	{ 191, "reserved_191" },
+	{ 192, "reserved_192" },
+	{ 193, "reserved_193" },
+	{ 194, "reserved_194" },
+	{ 195, "reserved_195" },
+	{ 196, "reserved_196" },
+	{ 197, "reserved_197" },
+	{ 198, "reserved_198" },
+	{ 199, "reserved_199" },
+	{ 200, "reserved_200" },
+	{ 201, "reserved_201" },
+	{ 202, "reserved_202" },
+	{ 203, "reserved_203" },
+	{ 204, "reserved_204" },
+	{ 205, "reserved_205" },
+	{ 206, "reserved_206" },
+	{ 207, "reserved_207" },
+	{ 208, "reserved_208" },
+	{ 209, "reserved_209" },
+	{ 210, "reserved_210" },
+	{ 211, "reserved_211" },
+	{ 212, "reserved_212" },
+	{ 213, "reserved_213" },
+	{ 214, "reserved_214" },
+	{ 215, "reserved_215" },
+	{ 216, "reserved_216" },
+	{ 217, "reserved_217" },
+	{ 218, "reserved_218" },
+	{ 219, "reserved_219" },
+	{ 220, "reserved_220" },
+	{ 221, "reserved_221" },
+	{ 222, "reserved_222" },
+	{ 223, "reserved_223" },
+	{ 224, "reserved_224" },
+	{ 225, "reserved_225" },
+	{ 226, "reserved_226" },
+	{ 227, "reserved_227" },
+	{ 228, "reserved_228" },
+	{ 229, "reserved_229" },
+	{ 230, "reserved_230" },
+	{ 231, "reserved_231" },
+	{ 232, "reserved_232" },
+	{ 233, "reserved_233" },
+	{ 234, "reserved_234" },
+	{ 235, "reserved_235" },
+	{ 236, "reserved_236" },
+	{ 237, "reserved_237" },
+	{ 238, "reserved_238" },
+	{ 239, "reserved_239" },
+	{ 240, "reserved_240" },
+	{ 241, "reserved_241" },
+	{ 242, "reserved_242" },
+	{ 243, "reserved_243" },
+	{ 244, "reserved_244" },
+	{ 245, "reserved_245" },
+	{ 246, "reserved_246" },
+	{ 247, "reserved_247" },
+	{ 248, "reserved_248" },
+	{ 249, "reserved_249" },
+	{ 250, "reserved_250" },
+	{ 251, "reserved_251" },
+	{ 252, "reserved_252" },
+	{ 253, "reserved_253" },
+	{ 254, "reserved_254" },
+	{ 255, "reserved_255" },
+	{ 256, "reserved_256" },
+	{ 257, "reserved_257" },
+	{ 258, "reserved_258" },
+	{ 259, "reserved_259" },
+	{ 260, "reserved_260" },
+	{ 261, "reserved_261" },
+	{ 262, "reserved_262" },
+	{ 263, "reserved_263" },
+	{ 264, "reserved_264" },
+	{ 265, "reserved_265" },
+	{ 266, "reserved_266" },
+	{ 267, "reserved_267" },
+	{ 268, "reserved_268" },
+	{ 269, "reserved_269" },
+	{ 270, "reserved_270" },
+	{ 271, "reserved_271" },
+	{ 272, "dfwx_flags" },
+	{ 273, "dfwx_slot" },
+	{ 274, "dfwx_client_data_addr_lo" },
+	{ 275, "dfwx_client_data_addr_hi" },
+	{ 276, "reserved_276" },
+	{ 277, "reserved_277" },
+	{ 278, "reserved_278" },
+	{ 279, "reserved_279" },
+	{ 280, "reserved_280" },
+	{ 281, "reserved_281" },
+	{ 282, "reserved_282" },
+	{ 283, "reserved_283" },
+	{ 284, "reserved_284" },
+	{ 285, "reserved_285" },
+	{ 286, "reserved_286" },
+	{ 287, "reserved_287" },
+	{ 288, "reserved_288" },
+	{ 289, "reserved_289" },
+	{ 290, "reserved_290" },
+	{ 291, "reserved_291" },
+	{ 292, "reserved_292" },
+	{ 293, "reserved_293" },
+	{ 294, "reserved_294" },
+	{ 295, "reserved_295" },
+	{ 296, "reserved_296" },
+	{ 297, "reserved_297" },
+	{ 298, "reserved_298" },
+	{ 299, "reserved_299" },
+	{ 300, "reserved_300" },
+	{ 301, "reserved_301" },
+	{ 302, "reserved_302" },
+	{ 303, "reserved_303" },
+	{ 304, "reserved_304" },
+	{ 305, "reserved_305" },
+	{ 306, "reserved_306" },
+	{ 307, "reserved_307" },
+	{ 308, "reserved_308" },
+	{ 309, "reserved_309" },
+	{ 310, "reserved_310" },
+	{ 311, "reserved_311" },
+	{ 312, "reserved_312" },
+	{ 313, "reserved_313" },
+	{ 314, "reserved_314" },
+	{ 315, "reserved_315" },
+	{ 316, "reserved_316" },
+	{ 317, "reserved_317" },
+	{ 318, "reserved_318" },
+	{ 319, "reserved_319" },
+	{ 320, "reserved_320" },
+	{ 321, "reserved_321" },
+	{ 322, "reserved_322" },
+	{ 323, "reserved_323" },
+	{ 324, "reserved_324" },
+	{ 325, "reserved_325" },
+	{ 326, "reserved_326" },
+	{ 327, "reserved_327" },
+	{ 328, "reserved_328" },
+	{ 329, "reserved_329" },
+	{ 330, "reserved_330" },
+	{ 331, "reserved_331" },
+	{ 332, "reserved_332" },
+	{ 333, "reserved_333" },
+	{ 334, "reserved_334" },
+	{ 335, "reserved_335" },
+	{ 336, "reserved_336" },
+	{ 337, "reserved_337" },
+	{ 338, "reserved_338" },
+	{ 339, "reserved_339" },
+	{ 340, "reserved_340" },
+	{ 341, "reserved_341" },
+	{ 342, "reserved_342" },
+	{ 343, "reserved_343" },
+	{ 344, "reserved_344" },
+	{ 345, "reserved_345" },
+	{ 346, "reserved_346" },
+	{ 347, "reserved_347" },
+	{ 348, "reserved_348" },
+	{ 349, "reserved_349" },
+	{ 350, "reserved_350" },
+	{ 351, "reserved_351" },
+	{ 352, "reserved_352" },
+	{ 353, "reserved_353" },
+	{ 354, "reserved_354" },
+	{ 355, "reserved_355" },
+	{ 356, "reserved_356" },
+	{ 357, "reserved_357" },
+	{ 358, "reserved_358" },
+	{ 359, "reserved_359" },
+	{ 360, "reserved_360" },
+	{ 361, "reserved_361" },
+	{ 362, "reserved_362" },
+	{ 363, "reserved_363" },
+	{ 364, "reserved_364" },
+	{ 365, "reserved_365" },
+	{ 366, "reserved_366" },
+	{ 367, "reserved_367" },
+	{ 368, "reserved_368" },
+	{ 369, "reserved_369" },
+	{ 370, "reserved_370" },
+	{ 371, "reserved_371" },
+	{ 372, "reserved_372" },
+	{ 373, "reserved_373" },
+	{ 374, "reserved_374" },
+	{ 375, "reserved_375" },
+	{ 376, "reserved_376" },
+	{ 377, "reserved_377" },
+	{ 378, "reserved_378" },
+	{ 379, "reserved_379" },
+	{ 380, "reserved_380" },
+	{ 381, "reserved_381" },
+	{ 382, "reserved_382" },
+	{ 383, "reserved_383" },
+	{ 384, "reserved_384" },
+	{ 385, "reserved_385" },
+	{ 386, "reserved_386" },
+	{ 387, "reserved_387" },
+	{ 388, "reserved_388" },
+	{ 389, "reserved_389" },
+	{ 390, "reserved_390" },
+	{ 391, "reserved_391" },
+	{ 392, "reserved_392" },
+	{ 393, "reserved_393" },
+	{ 394, "reserved_394" },
+	{ 395, "reserved_395" },
+	{ 396, "reserved_396" },
+	{ 397, "reserved_397" },
+	{ 398, "reserved_398" },
+	{ 399, "reserved_399" },
+	{ 400, "reserved_400" },
+	{ 401, "reserved_401" },
+	{ 402, "reserved_402" },
+	{ 403, "reserved_403" },
+	{ 404, "reserved_404" },
+	{ 405, "reserved_405" },
+	{ 406, "reserved_406" },
+	{ 407, "reserved_407" },
+	{ 408, "reserved_408" },
+	{ 409, "reserved_409" },
+	{ 410, "reserved_410" },
+	{ 411, "reserved_411" },
+	{ 412, "reserved_412" },
+	{ 413, "reserved_413" },
+	{ 414, "reserved_414" },
+	{ 415, "reserved_415" },
+	{ 416, "reserved_416" },
+	{ 417, "reserved_417" },
+	{ 418, "reserved_418" },
+	{ 419, "reserved_419" },
+	{ 420, "reserved_420" },
+	{ 421, "reserved_421" },
+	{ 422, "reserved_422" },
+	{ 423, "reserved_423" },
+	{ 424, "reserved_424" },
+	{ 425, "reserved_425" },
+	{ 426, "reserved_426" },
+	{ 427, "reserved_427" },
+	{ 428, "reserved_428" },
+	{ 429, "reserved_429" },
+	{ 430, "reserved_430" },
+	{ 431, "reserved_431" },
+	{ 432, "reserved_432" },
+	{ 433, "reserved_433" },
+	{ 434, "reserved_434" },
+	{ 435, "reserved_435" },
+	{ 436, "reserved_436" },
+	{ 437, "reserved_437" },
+	{ 438, "reserved_438" },
+	{ 439, "reserved_439" },
+	{ 440, "reserved_440" },
+	{ 441, "reserved_441" },
+	{ 442, "reserved_442" },
+	{ 443, "reserved_443" },
+	{ 444, "reserved_444" },
+	{ 445, "reserved_445" },
+	{ 446, "reserved_446" },
+	{ 447, "reserved_447" },
+	{ 448, "reserved_448" },
+	{ 449, "reserved_449" },
+	{ 450, "reserved_450" },
+	{ 451, "reserved_451" },
+	{ 452, "reserved_452" },
+	{ 453, "reserved_453" },
+	{ 454, "reserved_454" },
+	{ 455, "reserved_455" },
+	{ 456, "reserved_456" },
+	{ 457, "reserved_457" },
+	{ 458, "reserved_458" },
+	{ 459, "reserved_459" },
+	{ 460, "reserved_460" },
+	{ 461, "reserved_461" },
+	{ 462, "reserved_462" },
+	{ 463, "reserved_463" },
+	{ 464, "reserved_464" },
+	{ 465, "reserved_465" },
+	{ 466, "reserved_466" },
+	{ 467, "reserved_467" },
+	{ 468, "reserved_468" },
+	{ 469, "reserved_469" },
+	{ 470, "reserved_470" },
+	{ 471, "reserved_471" },
+	{ 472, "reserved_472" },
+	{ 473, "reserved_473" },
+	{ 474, "reserved_474" },
+	{ 475, "reserved_475" },
+	{ 476, "reserved_476" },
+	{ 477, "reserved_477" },
+	{ 478, "reserved_478" },
+	{ 479, "reserved_479" },
+	{ 480, "reserved_480" },
+	{ 481, "reserved_481" },
+	{ 482, "reserved_482" },
+	{ 483, "reserved_483" },
+	{ 484, "reserved_484" },
+	{ 485, "reserved_485" },
+	{ 486, "reserved_486" },
+	{ 487, "reserved_487" },
+	{ 488, "reserved_488" },
+	{ 489, "reserved_489" },
+	{ 490, "reserved_490" },
+	{ 491, "reserved_491" },
+	{ 492, "reserved_492" },
+	{ 493, "reserved_493" },
+	{ 494, "reserved_494" },
+	{ 495, "reserved_495" },
+	{ 496, "reserved_496" },
+	{ 497, "reserved_497" },
+	{ 498, "reserved_498" },
+	{ 499, "reserved_499" },
+	{ 500, "reserved_500" },
+	{ 501, "reserved_501" },
+	{ 502, "reserved_502" },
+	{ 503, "reserved_503" },
+	{ 504, "reserved_504" },
+	{ 505, "reserved_505" },
+	{ 506, "reserved_506" },
+	{ 507, "reserved_507" },
+	{ 508, "reserved_508" },
+	{ 509, "reserved_509" },
+	{ 510, "reserved_510" },
+	{ 511, "reserved_511" },
+};
+
+static const struct umr_mqd_fields  umr_mqd_sdma_gfx12[] = {
+	{ 0, "sdmax_rlcx_rb_cntl" },
+	{ 1, "sdmax_rlcx_rb_base" },
+	{ 2, "sdmax_rlcx_rb_base_hi" },
+	{ 3, "sdmax_rlcx_rb_rptr" },
+	{ 4, "sdmax_rlcx_rb_rptr_hi" },
+	{ 5, "sdmax_rlcx_rb_wptr" },
+	{ 6, "sdmax_rlcx_rb_wptr_hi" },
+	{ 7, "sdmax_rlcx_rb_rptr_addr_lo" },
+	{ 8, "sdmax_rlcx_rb_rptr_addr_hi" },
+	{ 9, "sdmax_rlcx_ib_cntl" },
+	{ 10, "sdmax_rlcx_ib_rptr" },
+	{ 11, "sdmax_rlcx_ib_offset" },
+	{ 12, "sdmax_rlcx_ib_base_lo" },
+	{ 13, "sdmax_rlcx_ib_base_hi" },
+	{ 14, "sdmax_rlcx_ib_size" },
+	{ 15, "sdmax_rlcx_doorbell" },
+	{ 16, "sdmax_rlcx_doorbell_log" },
+	{ 17, "sdmax_rlcx_doorbell_offset" },
+	{ 18, "sdmax_rlcx_csa_addr_lo" },
+	{ 19, "sdmax_rlcx_csa_addr_hi" },
+	{ 20, "sdmax_rlcx_sched_cntl" },
+	{ 21, "sdmax_rlcx_ib_sub_remain" },
+	{ 22, "sdmax_rlcx_preempt" },
+	{ 23, "sdmax_rlcx_dummy_reg" },
+	{ 24, "sdmax_rlcx_rb_wptr_poll_addr_lo" },
+	{ 25, "sdmax_rlcx_rb_wptr_poll_addr_hi" },
+	{ 26, "sdmax_rlcx_rb_aql_cntl" },
+	{ 27, "sdmax_rlcx_minor_ptr_update" },
+	{ 28, "sdmax_rlcx_mcu_dbg0" },
+	{ 29, "sdmax_rlcx_mcu_dbg1" },
+	{ 30, "sdmax_rlcx_context_switch_status" },
+	{ 31, "sdmax_rlcx_midcmd_cntl" },
+	{ 32, "sdmax_rlcx_midcmd_data0" },
+	{ 33, "sdmax_rlcx_midcmd_data1" },
+	{ 34, "sdmax_rlcx_midcmd_data2" },
+	{ 35, "sdmax_rlcx_midcmd_data3" },
+	{ 36, "sdmax_rlcx_midcmd_data4" },
+	{ 37, "sdmax_rlcx_midcmd_data5" },
+	{ 38, "sdmax_rlcx_midcmd_data6" },
+	{ 39, "sdmax_rlcx_midcmd_data7" },
+	{ 40, "sdmax_rlcx_midcmd_data8" },
+	{ 41, "sdmax_rlcx_midcmd_data9" },
+	{ 42, "sdmax_rlcx_midcmd_data10" },
+	{ 43, "sdmax_rlcx_wait_unsatisfied_thd" },
+	{ 44, "sdmax_rlcx_mqd_base_addr_lo" },
+	{ 45, "sdmax_rlcx_mqd_base_addr_hi" },
+	{ 46, "sdmax_rlcx_mqd_control" },
+	{ 47, "reserved_47" },
+	{ 48, "reserved_48" },
+	{ 49, "reserved_49" },
+	{ 50, "reserved_50" },
+	{ 51, "reserved_51" },
+	{ 52, "reserved_52" },
+	{ 53, "reserved_53" },
+	{ 54, "reserved_54" },
+	{ 55, "reserved_55" },
+	{ 56, "reserved_56" },
+	{ 57, "reserved_57" },
+	{ 58, "reserved_58" },
+	{ 59, "reserved_59" },
+	{ 60, "reserved_60" },
+	{ 61, "reserved_61" },
+	{ 62, "reserved_62" },
+	{ 63, "reserved_63" },
+	{ 64, "reserved_64" },
+	{ 65, "reserved_65" },
+	{ 66, "reserved_66" },
+	{ 67, "reserved_67" },
+	{ 68, "reserved_68" },
+	{ 69, "reserved_69" },
+	{ 70, "reserved_70" },
+	{ 0, "reserved_71" },
+	{ 1, "reserved_72" },
+	{ 2, "reserved_73" },
+	{ 3, "reserved_74" },
+	{ 4, "reserved_75" },
+	{ 5, "reserved_76" },
+	{ 6, "reserved_77" },
+	{ 7, "reserved_78" },
+	{ 79, "reserved_79" },
+	{ 80, "reserved_80" },
+	{ 81, "reserved_81" },
+	{ 82, "reserved_82" },
+	{ 83, "reserved_83" },
+	{ 84, "reserved_84" },
+	{ 85, "reserved_85" },
+	{ 86, "reserved_86" },
+	{ 87, "reserved_87" },
+	{ 88, "reserved_88" },
+	{ 89, "reserved_89" },
+	{ 90, "reserved_90" },
+	{ 91, "reserved_91" },
+	{ 92, "reserved_92" },
+	{ 93, "reserved_93" },
+	{ 94, "reserved_94" },
+	{ 95, "reserved_95" },
+	{ 96, "reserved_96" },
+	{ 97, "reserved_97" },
+	{ 98, "reserved_98" },
+	{ 99, "reserved_99" },
+	{ 100, "reserved_100" },
+	{ 101, "reserved_101" },
+	{ 102, "reserved_102" },
+	{ 103, "reserved_103" },
+	{ 104, "reserved_104" },
+	{ 105, "reserved_105" },
+	{ 106, "reserved_106" },
+	{ 107, "reserved_107" },
+	{ 108, "reserved_108" },
+	{ 109, "reserved_109" },
+	{ 110, "reserved_110" },
+	{ 111, "reserved_111" },
+	{ 112, "reserved_112" },
+	{ 113, "reserved_113" },
+	{ 114, "reserved_114" },
+	{ 115, "reserved_115" },
+	{ 116, "reserved_116" },
+	{ 117, "reserved_117" },
+	{ 118, "reserved_118" },
+	{ 119, "reserved_119" },
+	{ 120, "reserved_120" },
+	{ 121, "reserved_121" },
+	{ 122, "reserved_122" },
+	{ 123, "reserved_123" },
+	{ 124, "reserved_124" },
+	{ 125, "reserved_125" },
+	{ 126, "sdma_engine_id" },
+	{ 127, "sdma_queue_id" },
+};
+
+static const struct umr_mqd_fields  umr_mqd_compute_gfx12 [] = {
+	{ 0, "header" },
+	{ 1, "compute_dispatch_initiator" },
+	{ 2, "compute_dim_x" },
+	{ 3, "compute_dim_y" },
+	{ 4, "compute_dim_z" },
+	{ 5, "compute_start_x" },
+	{ 6, "compute_start_y" },
+	{ 7, "compute_start_z" },
+	{ 8, "compute_num_thread_x" },
+	{ 9, "compute_num_thread_y" },
+	{ 10, "compute_num_thread_z" },
+	{ 11, "compute_pipelinestat_enable" },
+	{ 12, "compute_perfcount_enable" },
+	{ 13, "compute_pgm_lo" },
+	{ 14, "compute_pgm_hi" },
+	{ 15, "compute_dispatch_pkt_addr_lo" },
+	{ 16, "compute_dispatch_pkt_addr_hi" },
+	{ 17, "compute_dispatch_scratch_base_lo" },
+	{ 18, "compute_dispatch_scratch_base_hi" },
+	{ 19, "compute_pgm_rsrc1" },
+	{ 20, "compute_pgm_rsrc2" },
+	{ 21, "compute_vmid" },
+	{ 22, "compute_resource_limits" },
+	{ 23, "compute_static_thread_mgmt_se0" },
+	{ 24, "compute_static_thread_mgmt_se1" },
+	{ 25, "compute_tmpring_size" },
+	{ 26, "compute_static_thread_mgmt_se2" },
+	{ 27, "compute_static_thread_mgmt_se3" },
+	{ 28, "compute_restart_x" },
+	{ 29, "compute_restart_y" },
+	{ 30, "compute_restart_z" },
+	{ 31, "compute_thread_trace_enable" },
+	{ 32, "compute_misc_reserved" },
+	{ 33, "compute_dispatch_id" },
+	{ 34, "compute_threadgroup_id" },
+	{ 35, "compute_req_ctrl" },
+	{ 36, "reserved_36" },
+	{ 37, "compute_user_accum_0" },
+	{ 38, "compute_user_accum_1" },
+	{ 39, "compute_user_accum_2" },
+	{ 40, "compute_user_accum_3" },
+	{ 41, "compute_pgm_rsrc3" },
+	{ 42, "compute_ddid_index" },
+	{ 43, "compute_shader_chksum" },
+	{ 44, "compute_static_thread_mgmt_se4" },
+	{ 45, "compute_static_thread_mgmt_se5" },
+	{ 46, "compute_static_thread_mgmt_se6" },
+	{ 47, "compute_static_thread_mgmt_se7" },
+	{ 48, "compute_dispatch_interleave" },
+	{ 49, "compute_relaunch" },
+	{ 50, "compute_wave_restore_addr_lo" },
+	{ 51, "compute_wave_restore_addr_hi" },
+	{ 52, "compute_wave_restore_control" },
+	{ 53, "reserved_53" },
+	{ 54, "reserved_54" },
+	{ 55, "reserved_55" },
+	{ 56, "reserved_56" },
+	{ 57, "reserved_57" },
+	{ 58, "reserved_58" },
+	{ 59, "compute_static_thread_mgmt_se8" },
+	{ 60, "reserved_60" },
+	{ 61, "reserved_61" },
+	{ 62, "reserved_62" },
+	{ 63, "reserved_63" },
+	{ 64, "reserved_64" },
+	{ 65, "compute_user_data_0" },
+	{ 66, "compute_user_data_1" },
+	{ 67, "compute_user_data_2" },
+	{ 68, "compute_user_data_3" },
+	{ 69, "compute_user_data_4" },
+	{ 70, "compute_user_data_5" },
+	{ 71, "compute_user_data_6" },
+	{ 72, "compute_user_data_7" },
+	{ 73, "compute_user_data_8" },
+	{ 74, "compute_user_data_9" },
+	{ 75, "compute_user_data_10" },
+	{ 76, "compute_user_data_11" },
+	{ 77, "compute_user_data_12" },
+	{ 78, "compute_user_data_13" },
+	{ 79, "compute_user_data_14" },
+	{ 80, "compute_user_data_15" },
+	{ 81, "cp_compute_csinvoc_count_lo" },
+	{ 82, "cp_compute_csinvoc_count_hi" },
+	{ 83, "reserved_83" },
+	{ 84, "reserved_84" },
+	{ 85, "reserved_85" },
+	{ 86, "cp_mqd_query_time_lo" },
+	{ 87, "cp_mqd_query_time_hi" },
+	{ 88, "cp_mqd_connect_start_time_lo" },
+	{ 89, "cp_mqd_connect_start_time_hi" },
+	{ 90, "cp_mqd_connect_end_time_lo" },
+	{ 91, "cp_mqd_connect_end_time_hi" },
+	{ 92, "cp_mqd_connect_end_wf_count" },
+	{ 93, "cp_mqd_connect_end_pq_rptr" },
+	{ 94, "cp_mqd_connect_end_pq_wptr" },
+	{ 95, "cp_mqd_connect_end_ib_rptr" },
+	{ 96, "cp_mqd_readindex_lo" },
+	{ 97, "cp_mqd_readindex_hi" },
+	{ 98, "cp_mqd_save_start_time_lo" },
+	{ 99, "cp_mqd_save_start_time_hi" },
+	{ 100, "cp_mqd_save_end_time_lo" },
+	{ 101, "cp_mqd_save_end_time_hi" },
+	{ 102, "cp_mqd_restore_start_time_lo" },
+	{ 103, "cp_mqd_restore_start_time_hi" },
+	{ 104, "cp_mqd_restore_end_time_lo" },
+	{ 105, "cp_mqd_restore_end_time_hi" },
+	{ 106, "disable_queue" },
+	{ 107, "reserved_107" },
+	{ 108, "reserved_108" },
+	{ 109, "reserved_109" },
+	{ 110, "reserved_110" },
+	{ 111, "reserved_111" },
+	{ 112, "reserved_112" },
+	{ 113, "reserved_113" },
+	{ 114, "cp_pq_exe_status_lo" },
+	{ 115, "cp_pq_exe_status_hi" },
+	{ 116, "cp_packet_id_lo" },
+	{ 117, "cp_packet_id_hi" },
+	{ 118, "cp_packet_exe_status_lo" },
+	{ 119, "cp_packet_exe_status_hi" },
+	{ 120, "reserved_120" },
+	{ 121, "reserved_121" },
+	{ 122, "reserved_122" },
+	{ 123, "reserved_123" },
+	{ 124, "ctx_save_base_addr_lo" },
+	{ 125, "ctx_save_base_addr_hi" },
+	{ 126, "reserved_126" },
+	{ 127, "reserved_127" },
+	{ 128, "cp_mqd_base_addr_lo" },
+	{ 129, "cp_mqd_base_addr_hi" },
+	{ 130, "cp_hqd_active" },
+	{ 131, "cp_hqd_vmid" },
+	{ 132, "cp_hqd_persistent_state" },
+	{ 133, "cp_hqd_pipe_priority" },
+	{ 134, "cp_hqd_queue_priority" },
+	{ 135, "cp_hqd_quantum" },
+	{ 136, "cp_hqd_pq_base_lo" },
+	{ 137, "cp_hqd_pq_base_hi" },
+	{ 138, "cp_hqd_pq_rptr" },
+	{ 139, "cp_hqd_pq_rptr_report_addr_lo" },
+	{ 140, "cp_hqd_pq_rptr_report_addr_hi" },
+	{ 141, "cp_hqd_pq_wptr_poll_addr_lo" },
+	{ 142, "cp_hqd_pq_wptr_poll_addr_hi" },
+	{ 143, "cp_hqd_pq_doorbell_control" },
+	{ 144, "reserved_144" },
+	{ 145, "cp_hqd_pq_control" },
+	{ 146, "cp_hqd_ib_base_addr_lo" },
+	{ 147, "cp_hqd_ib_base_addr_hi" },
+	{ 148, "cp_hqd_ib_rptr" },
+	{ 149, "cp_hqd_ib_control" },
+	{ 150, "cp_hqd_iq_timer" },
+	{ 151, "cp_hqd_iq_rptr" },
+	{ 152, "cp_hqd_dequeue_request" },
+	{ 153, "cp_hqd_dma_offload" },
+	{ 154, "cp_hqd_sema_cmd" },
+	{ 155, "cp_hqd_msg_type" },
+	{ 156, "cp_hqd_atomic0_preop_lo" },
+	{ 157, "cp_hqd_atomic0_preop_hi" },
+	{ 158, "cp_hqd_atomic1_preop_lo" },
+	{ 159, "cp_hqd_atomic1_preop_hi" },
+	{ 160, "cp_hqd_hq_status0" },
+	{ 161, "cp_hqd_hq_control0" },
+	{ 162, "cp_mqd_control" },
+	{ 163, "cp_hqd_hq_status1" },
+	{ 164, "cp_hqd_hq_control1" },
+	{ 165, "cp_hqd_eop_base_addr_lo" },
+	{ 166, "cp_hqd_eop_base_addr_hi" },
+	{ 167, "cp_hqd_eop_control" },
+	{ 168, "cp_hqd_eop_rptr" },
+	{ 169, "cp_hqd_eop_wptr" },
+	{ 170, "cp_hqd_eop_done_events" },
+	{ 171, "cp_hqd_ctx_save_base_addr_lo" },
+	{ 172, "cp_hqd_ctx_save_base_addr_hi" },
+	{ 173, "cp_hqd_ctx_save_control" },
+	{ 174, "cp_hqd_cntl_stack_offset" },
+	{ 175, "cp_hqd_cntl_stack_size" },
+	{ 176, "cp_hqd_wg_state_offset" },
+	{ 177, "cp_hqd_ctx_save_size" },
+	{ 178, "reserved_178" },
+	{ 179, "cp_hqd_error" },
+	{ 180, "cp_hqd_eop_wptr_mem" },
+	{ 181, "cp_hqd_aql_control" },
+	{ 182, "cp_hqd_pq_wptr_lo" },
+	{ 183, "cp_hqd_pq_wptr_hi" },
+	{ 184, "reserved_184" },
+	{ 185, "reserved_185" },
+	{ 186, "reserved_186" },
+	{ 187, "reserved_187" },
+	{ 188, "reserved_188" },
+	{ 189, "reserved_189" },
+	{ 190, "reserved_190" },
+	{ 191, "reserved_191" },
+	{ 192, "iqtimer_pkt_header" },
+	{ 193, "iqtimer_pkt_dw0" },
+	{ 194, "iqtimer_pkt_dw1" },
+	{ 195, "iqtimer_pkt_dw2" },
+	{ 196, "iqtimer_pkt_dw3" },
+	{ 197, "iqtimer_pkt_dw4" },
+	{ 198, "iqtimer_pkt_dw5" },
+	{ 199, "iqtimer_pkt_dw6" },
+	{ 200, "iqtimer_pkt_dw7" },
+	{ 201, "iqtimer_pkt_dw8" },
+	{ 202, "iqtimer_pkt_dw9" },
+	{ 203, "iqtimer_pkt_dw10" },
+	{ 204, "iqtimer_pkt_dw11" },
+	{ 205, "iqtimer_pkt_dw12" },
+	{ 206, "iqtimer_pkt_dw13" },
+	{ 207, "iqtimer_pkt_dw14" },
+	{ 208, "iqtimer_pkt_dw15" },
+	{ 209, "iqtimer_pkt_dw16" },
+	{ 210, "iqtimer_pkt_dw17" },
+	{ 211, "iqtimer_pkt_dw18" },
+	{ 212, "iqtimer_pkt_dw19" },
+	{ 213, "iqtimer_pkt_dw20" },
+	{ 214, "iqtimer_pkt_dw21" },
+	{ 215, "iqtimer_pkt_dw22" },
+	{ 216, "iqtimer_pkt_dw23" },
+	{ 217, "iqtimer_pkt_dw24" },
+	{ 218, "iqtimer_pkt_dw25" },
+	{ 219, "iqtimer_pkt_dw26" },
+	{ 220, "iqtimer_pkt_dw27" },
+	{ 221, "iqtimer_pkt_dw28" },
+	{ 222, "iqtimer_pkt_dw29" },
+	{ 223, "iqtimer_pkt_dw30" },
+	{ 224, "iqtimer_pkt_dw31" },
+	{ 225, "reserved_225" },
+	{ 226, "reserved_226" },
+	{ 227, "reserved_227" },
+	{ 228, "set_resources_header" },
+	{ 229, "set_resources_dw1" },
+	{ 230, "set_resources_dw2" },
+	{ 231, "set_resources_dw3" },
+	{ 232, "set_resources_dw4" },
+	{ 233, "set_resources_dw5" },
+	{ 234, "set_resources_dw6" },
+	{ 235, "set_resources_dw7" },
+	{ 236, "reserved_236" },
+	{ 237, "reserved_237" },
+	{ 238, "reserved_238" },
+	{ 239, "reserved_239" },
+	{ 240, "queue_doorbell_id0" },
+	{ 241, "queue_doorbell_id1" },
+	{ 242, "queue_doorbell_id2" },
+	{ 243, "queue_doorbell_id3" },
+	{ 244, "queue_doorbell_id4" },
+	{ 245, "queue_doorbell_id5" },
+	{ 246, "queue_doorbell_id6" },
+	{ 247, "queue_doorbell_id7" },
+	{ 248, "queue_doorbell_id8" },
+	{ 249, "queue_doorbell_id9" },
+	{ 250, "queue_doorbell_id10" },
+	{ 251, "queue_doorbell_id11" },
+	{ 252, "queue_doorbell_id12" },
+	{ 253, "queue_doorbell_id13" },
+	{ 254, "queue_doorbell_id14" },
+	{ 255, "queue_doorbell_id15" },
+	{ 256, "control_buf_addr_lo" },
+	{ 257, "control_buf_addr_hi" },
+	{ 258, "control_buf_wptr_lo" },
+	{ 259, "control_buf_wptr_hi" },
+	{ 260, "control_buf_dptr_lo" },
+	{ 261, "control_buf_dptr_hi" },
+	{ 262, "control_buf_num_entries" },
+	{ 263, "draw_ring_addr_lo" },
+	{ 264, "draw_ring_addr_hi" },
+	{ 265, "reserved_265" },
+	{ 266, "reserved_266" },
+	{ 267, "reserved_267" },
+	{ 268, "reserved_268" },
+	{ 269, "reserved_269" },
+	{ 270, "reserved_270" },
+	{ 271, "reserved_271" },
+	{ 272, "dfwx_flags" },
+	{ 273, "dfwx_slot" },
+	{ 274, "dfwx_client_data_addr_lo" },
+	{ 275, "dfwx_client_data_addr_hi" },
+	{ 276, "reserved_276" },
+	{ 277, "reserved_277" },
+	{ 278, "reserved_278" },
+	{ 279, "reserved_279" },
+	{ 280, "reserved_280" },
+	{ 281, "reserved_281" },
+	{ 282, "reserved_282" },
+	{ 283, "reserved_283" },
+	{ 284, "reserved_284" },
+	{ 285, "reserved_285" },
+	{ 286, "reserved_286" },
+	{ 287, "reserved_287" },
+	{ 288, "reserved_288" },
+	{ 289, "reserved_289" },
+	{ 290, "reserved_290" },
+	{ 291, "reserved_291" },
+	{ 292, "reserved_292" },
+	{ 293, "reserved_293" },
+	{ 294, "reserved_294" },
+	{ 295, "reserved_295" },
+	{ 296, "reserved_296" },
+	{ 297, "reserved_297" },
+	{ 298, "reserved_298" },
+	{ 299, "reserved_299" },
+	{ 300, "reserved_300" },
+	{ 301, "reserved_301" },
+	{ 302, "reserved_302" },
+	{ 303, "reserved_303" },
+	{ 304, "reserved_304" },
+	{ 305, "reserved_305" },
+	{ 306, "reserved_306" },
+	{ 307, "reserved_307" },
+	{ 308, "reserved_308" },
+	{ 309, "reserved_309" },
+	{ 310, "reserved_310" },
+	{ 311, "reserved_311" },
+	{ 312, "reserved_312" },
+	{ 313, "reserved_313" },
+	{ 314, "reserved_314" },
+	{ 315, "reserved_315" },
+	{ 316, "reserved_316" },
+	{ 317, "reserved_317" },
+	{ 318, "reserved_318" },
+	{ 319, "reserved_319" },
+	{ 320, "reserved_320" },
+	{ 321, "reserved_321" },
+	{ 322, "reserved_322" },
+	{ 323, "reserved_323" },
+	{ 324, "reserved_324" },
+	{ 325, "reserved_325" },
+	{ 326, "reserved_326" },
+	{ 327, "reserved_327" },
+	{ 328, "reserved_328" },
+	{ 329, "reserved_329" },
+	{ 330, "reserved_330" },
+	{ 331, "reserved_331" },
+	{ 332, "reserved_332" },
+	{ 333, "reserved_333" },
+	{ 334, "reserved_334" },
+	{ 335, "reserved_335" },
+	{ 336, "reserved_336" },
+	{ 337, "reserved_337" },
+	{ 338, "reserved_338" },
+	{ 339, "reserved_339" },
+	{ 340, "reserved_340" },
+	{ 341, "reserved_341" },
+	{ 342, "reserved_342" },
+	{ 343, "reserved_343" },
+	{ 344, "reserved_344" },
+	{ 345, "reserved_345" },
+	{ 346, "reserved_346" },
+	{ 347, "reserved_347" },
+	{ 348, "reserved_348" },
+	{ 349, "reserved_349" },
+	{ 350, "reserved_350" },
+	{ 351, "reserved_351" },
+	{ 352, "reserved_352" },
+	{ 353, "reserved_353" },
+	{ 354, "reserved_354" },
+	{ 355, "reserved_355" },
+	{ 356, "reserved_356" },
+	{ 357, "reserved_357" },
+	{ 358, "reserved_358" },
+	{ 359, "reserved_359" },
+	{ 360, "reserved_360" },
+	{ 361, "reserved_361" },
+	{ 362, "reserved_362" },
+	{ 363, "reserved_363" },
+	{ 364, "reserved_364" },
+	{ 365, "reserved_365" },
+	{ 366, "reserved_366" },
+	{ 367, "reserved_367" },
+	{ 368, "reserved_368" },
+	{ 369, "reserved_369" },
+	{ 370, "reserved_370" },
+	{ 371, "reserved_371" },
+	{ 372, "reserved_372" },
+	{ 373, "reserved_373" },
+	{ 374, "reserved_374" },
+	{ 375, "reserved_375" },
+	{ 376, "reserved_376" },
+	{ 377, "reserved_377" },
+	{ 378, "reserved_378" },
+	{ 379, "reserved_379" },
+	{ 380, "reserved_380" },
+	{ 381, "reserved_381" },
+	{ 382, "reserved_382" },
+	{ 383, "reserved_383" },
+	{ 384, "reserved_384" },
+	{ 385, "reserved_385" },
+	{ 386, "reserved_386" },
+	{ 387, "reserved_387" },
+	{ 388, "reserved_388" },
+	{ 389, "reserved_389" },
+	{ 390, "reserved_390" },
+	{ 391, "reserved_391" },
+	{ 392, "reserved_392" },
+	{ 393, "reserved_393" },
+	{ 394, "reserved_394" },
+	{ 395, "reserved_395" },
+	{ 396, "reserved_396" },
+	{ 397, "reserved_397" },
+	{ 398, "reserved_398" },
+	{ 399, "reserved_399" },
+	{ 400, "reserved_400" },
+	{ 401, "reserved_401" },
+	{ 402, "reserved_402" },
+	{ 403, "reserved_403" },
+	{ 404, "reserved_404" },
+	{ 405, "reserved_405" },
+	{ 406, "reserved_406" },
+	{ 407, "reserved_407" },
+	{ 408, "reserved_408" },
+	{ 409, "reserved_409" },
+	{ 410, "reserved_410" },
+	{ 411, "reserved_411" },
+	{ 412, "reserved_412" },
+	{ 413, "reserved_413" },
+	{ 414, "reserved_414" },
+	{ 415, "reserved_415" },
+	{ 416, "reserved_416" },
+	{ 417, "reserved_417" },
+	{ 418, "reserved_418" },
+	{ 419, "reserved_419" },
+	{ 420, "reserved_420" },
+	{ 421, "reserved_421" },
+	{ 422, "reserved_422" },
+	{ 423, "reserved_423" },
+	{ 424, "reserved_424" },
+	{ 425, "reserved_425" },
+	{ 426, "reserved_426" },
+	{ 427, "reserved_427" },
+	{ 428, "reserved_428" },
+	{ 429, "reserved_429" },
+	{ 430, "reserved_430" },
+	{ 431, "reserved_431" },
+	{ 432, "reserved_432" },
+	{ 433, "reserved_433" },
+	{ 434, "reserved_434" },
+	{ 435, "reserved_435" },
+	{ 436, "reserved_436" },
+	{ 437, "reserved_437" },
+	{ 438, "reserved_438" },
+	{ 439, "reserved_439" },
+	{ 440, "reserved_440" },
+	{ 441, "reserved_441" },
+	{ 442, "reserved_442" },
+	{ 443, "reserved_443" },
+	{ 444, "reserved_444" },
+	{ 445, "reserved_445" },
+	{ 446, "reserved_446" },
+	{ 447, "reserved_447" },
+	{ 448, "gws_0_val" },
+	{ 449, "gws_1_val" },
+	{ 450, "gws_2_val" },
+	{ 451, "gws_3_val" },
+	{ 452, "gws_4_val" },
+	{ 453, "gws_5_val" },
+	{ 454, "gws_6_val" },
+	{ 455, "gws_7_val" },
+	{ 456, "gws_8_val" },
+	{ 457, "gws_9_val" },
+	{ 458, "gws_10_val" },
+	{ 459, "gws_11_val" },
+	{ 460, "gws_12_val" },
+	{ 461, "gws_13_val" },
+	{ 462, "gws_14_val" },
+	{ 463, "gws_15_val" },
+	{ 464, "gws_16_val" },
+	{ 465, "gws_17_val" },
+	{ 466, "gws_18_val" },
+	{ 467, "gws_19_val" },
+	{ 468, "gws_20_val" },
+	{ 469, "gws_21_val" },
+	{ 470, "gws_22_val" },
+	{ 471, "gws_23_val" },
+	{ 472, "gws_24_val" },
+	{ 473, "gws_25_val" },
+	{ 474, "gws_26_val" },
+	{ 475, "gws_27_val" },
+	{ 476, "gws_28_val" },
+	{ 477, "gws_29_val" },
+	{ 478, "gws_30_val" },
+	{ 479, "gws_31_val" },
+	{ 480, "gws_32_val" },
+	{ 481, "gws_33_val" },
+	{ 482, "gws_34_val" },
+	{ 483, "gws_35_val" },
+	{ 484, "gws_36_val" },
+	{ 485, "gws_37_val" },
+	{ 486, "gws_38_val" },
+	{ 487, "gws_39_val" },
+	{ 488, "gws_40_val" },
+	{ 489, "gws_41_val" },
+	{ 490, "gws_42_val" },
+	{ 491, "gws_43_val" },
+	{ 492, "gws_44_val" },
+	{ 493, "gws_45_val" },
+	{ 494, "gws_46_val" },
+	{ 495, "gws_47_val" },
+	{ 496, "gws_48_val" },
+	{ 497, "gws_49_val" },
+	{ 498, "gws_50_val" },
+	{ 499, "gws_51_val" },
+	{ 500, "gws_52_val" },
+	{ 501, "gws_53_val" },
+	{ 502, "gws_54_val" },
+	{ 503, "gws_55_val" },
+	{ 504, "gws_56_val" },
+	{ 505, "gws_57_val" },
+	{ 506, "gws_58_val" },
+	{ 507, "gws_59_val" },
+	{ 508, "gws_60_val" },
+	{ 509, "gws_61_val" },
+	{ 510, "gws_62_val" },
+	{ 511, "gws_63_val" },
+};
+
 static const struct umr_mqd_fields umr_mqd_compute_gfx11[] = {
 		{ 0, "header" },
 		{ 1, "compute_dispatch_initiator" },
@@ -1357,6 +2518,11 @@ static const struct {
 	const struct umr_mqd_fields *fields;
 } fields[] = {
 	// sort by highest family on top
+	{ UMR_MQD_ENGINE_MES,     FAMILY_GFX12, umr_mqd_compute_gfx12  },
+	{ UMR_MQD_ENGINE_COMPUTE, FAMILY_GFX12, umr_mqd_compute_gfx12  },
+	{ UMR_MQD_ENGINE_GFX,     FAMILY_GFX12, umr_mqd_graphics_gfx12 },
+	{ UMR_MQD_ENGINE_SDMA0,   FAMILY_GFX12, umr_mqd_sdma_gfx12 },
+	{ UMR_MQD_ENGINE_MES,     FAMILY_GFX11, umr_mqd_compute_gfx11  },
 	{ UMR_MQD_ENGINE_COMPUTE, FAMILY_GFX11, umr_mqd_compute_gfx11  },
 	{ UMR_MQD_ENGINE_GFX,     FAMILY_GFX11, umr_mqd_graphics_gfx11 },
 	{ UMR_MQD_ENGINE_SDMA0,   FAMILY_GFX11, umr_mqd_sdma_gfx11 },
@@ -1417,7 +2583,7 @@ char **umr_mqd_decode_data(enum umr_mqd_engine_sel eng, enum chipfamily fam, uin
 	if (!y) {
 		return NULL;
 	}
-	txt = calloc(y, sizeof(*txt));
+	txt = calloc(y + 1, sizeof(*txt));
 	for (x = 0; fields[x].fields != NULL; x++) {
 		if (eng == fields[x].eng && fam >= fields[x].family) {
 			m = fields[x].fields;
diff --git a/src/lib/pm4_decode_opcodes.c b/src/lib/pm4_decode_opcodes.c
index a7567a0dba2bdf8c6fb9de59a88308728286d343..7df2cfadfab8b8c11cf9c79cb837b35fc1fe97c8 100644
--- a/src/lib/pm4_decode_opcodes.c
+++ b/src/lib/pm4_decode_opcodes.c
@@ -221,13 +221,13 @@ static const char *pm4_pkt3_opcode_names[] = {
 	"UNK", // b5
 	"UNK", // b6
 	"UNK", // b7
-	"UNK", // b8
-	"UNK", // b9
-	"UNK", // ba
+	"PKT3_SET_CONTEXT_REG_PAIRS", // b8
+	"PKT3_SET_CONTEXT_REG_PAIRS_PACKED", // b9
+	"PKT3_SET_SH_REG_PAIRS", // ba
 	"UNK", // bb
-	"UNK", // bc
-	"UNK", // bd
-	"UNK", // be
+	"PKT3_SET_SH_REG_PAIRS_PACKED", // bc
+	"PKT3_SET_SH_REG_PAIRS_PACKED_N", // bd
+	"PKT3_SET_UCONFIG_REG_PAIRS", // be
 	"UNK", // bf
 	"UNK", // c0
 	"UNK", // c1
@@ -678,7 +678,7 @@ static void decode_pkt3_gfx8(struct umr_asic *asic, struct umr_stream_decode_ui
 			ui->add_field(ui, ib_addr + 20, ib_vmid, "DATA_LO", fetch_word(asic, stream, 4), NULL, 16, 32);
 			ui->add_field(ui, ib_addr + 24, ib_vmid, "DATA_HI", fetch_word(asic, stream, 5), NULL, 16, 32);
 			break;
-		case 0x4A: // PREABMLE_CNTL
+		case 0x4A: // PREAMBLE_CNTL
 			ui->add_field(ui, ib_addr + 4, ib_vmid, "COMMAND", BITS(fetch_word(asic, stream, 0), 28, 32), NULL, 16, 32);
 			break;
 		case 0x50: // DMA_DATA
@@ -1336,7 +1336,7 @@ static void decode_pkt3_gfx10(struct umr_asic *asic, struct umr_stream_decode_ui
 			if (asic->family >= FAMILY_AI)
 				ui->add_field(ui, ib_addr + 28, ib_vmid, "INT_CTXID", fetch_word(asic, stream, 6), NULL, 16, 32);
 			break;
-		case 0x4A: // PREABMLE_CNTL
+		case 0x4A: // PREAMBLE_CNTL
 			ui->add_field(ui, ib_addr + 4, ib_vmid, "COMMAND", BITS(fetch_word(asic, stream, 0), 28, 32), NULL, 16, 32);
 			break;
 		case 0x4C: // DISPATCH_MESH_INDIRECT_MULTI
@@ -1624,28 +1624,32 @@ static void decode_pkt3_gfx11(struct umr_asic *asic, struct umr_stream_decode_ui
 			}
 			break;
 		case 0xA2: // PKT3_MAP_QUEUES
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "EXTENDED_ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 2, 4), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_SEL", BITS(fetch_word(asic, stream, 0), 4, 6), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "VMID", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE", BITS(fetch_word(asic, stream, 0), 13, 21), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_TYPE", BITS(fetch_word(asic, stream, 0), 21, 24), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "STATIC_QUEUE_GROUP", BITS(fetch_word(asic, stream, 0), 24, 26), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 26, 29), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 4, ib_vmid, "NUM_QUEUES", BITS(fetch_word(asic, stream, 0), 29, 32), NULL, 10, 32);
-			ui->add_field(ui, ib_addr + 8, ib_vmid, "CHECK_DISABLE", BITS(fetch_word(asic, stream, 1), 1, 2), NULL, 16, 32);
-			ui->add_field(ui, ib_addr + 8, ib_vmid, "DOORBELL_OFFSET", BITS(fetch_word(asic, stream, 1), 2, 28), NULL, 16, 32);
-			{
-				uint32_t n;
-				for (n = 2; n + 4 <= stream->n_words; n += 4) {
-					ui->add_field(ui, ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_LO", fetch_word(asic, stream, n), NULL, 16, 32);
-					ui->add_field(ui, ib_addr + 16 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_HI", fetch_word(asic, stream, n + 1), NULL, 16, 32);
-					ui->add_field(ui, ib_addr + 20 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_LO", fetch_word(asic, stream, n + 2), NULL, 16, 32);
-					ui->add_field(ui, ib_addr + 24 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_HI", fetch_word(asic, stream, n + 3), NULL, 16, 32);
-					if (ui->add_data)
-						ui->add_data(ui, asic,
-									 ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid,
-									 ((uint64_t)fetch_word(asic, stream, n)) | (((uint64_t)fetch_word(asic, stream, n + 1)) << 32), BITS(fetch_word(asic, stream, 0), 8, 12),
-									 UMR_DATABLOCK_MQD_NV, BITS(fetch_word(asic, stream, 0), 26, 29));
+			{ uint32_t ext_sel = BITS(fetch_word(asic, stream, 0), 2, 4),
+					   engine_sel = BITS(fetch_word(asic, stream, 0), 26, 29);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "EXTENDED_ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 2, 4), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_SEL", BITS(fetch_word(asic, stream, 0), 4, 6), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "VMID", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE", BITS(fetch_word(asic, stream, 0), 13, 21), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_TYPE", BITS(fetch_word(asic, stream, 0), 21, 24), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "STATIC_QUEUE_GROUP", BITS(fetch_word(asic, stream, 0), 24, 26), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 26, 29), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "NUM_QUEUES", BITS(fetch_word(asic, stream, 0), 29, 32), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "CHECK_DISABLE", BITS(fetch_word(asic, stream, 1), 1, 2), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "DOORBELL_OFFSET", BITS(fetch_word(asic, stream, 1), 2, 28), NULL, 16, 32);
+				{
+					uint32_t n;
+					for (n = 2; n + 4 <= stream->n_words; n += 4) {
+						ui->add_field(ui, ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_LO", fetch_word(asic, stream, n), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 16 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_HI", fetch_word(asic, stream, n + 1), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 20 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_LO", fetch_word(asic, stream, n + 2), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 24 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_HI", fetch_word(asic, stream, n + 3), NULL, 16, 32);
+						if (ui->add_data)
+							ui->add_data(ui, asic,
+										 ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid,
+										 ((uint64_t)fetch_word(asic, stream, n)) | (((uint64_t)fetch_word(asic, stream, n + 1)) << 32), BITS(fetch_word(asic, stream, 0), 8, 12),
+										 UMR_DATABLOCK_MQD_NV, ext_sel == 0 ? engine_sel : 2);
+										 // send SDMA0 if extended_engine_sel is enabled for now
+					}
 				}
 			}
 			break;
@@ -1686,6 +1690,319 @@ static void decode_pkt3_gfx11(struct umr_asic *asic, struct umr_stream_decode_ui
 	}
 }
 
+static void decode_pkt3_gfx12(struct umr_asic *asic, struct umr_stream_decode_ui *ui, struct umr_pm4_stream *stream, uint64_t ib_addr, uint32_t ib_vmid)
+{
+	switch (stream->opcode) {
+		case 0x1d: // ATOMIC_GDS
+			// TODO: fill in
+			break;
+		case 0x1e: // ATOMIC_MEM
+			// TODO: fill in
+			break;
+		case 0x33: // INDIRECT_BUFFER_CONST
+		case 0x3F: // INDIRECT_BUFFER_CIK
+			if (stream->opcode == 0x3F && stream->n_words == 13) {
+				// COND packet
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "MODE", BITS(fetch_word(asic, stream, 0), 0, 2), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "FUNCTION", BITS(fetch_word(asic, stream, 0), 8, 11), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "COMPARE_ADDR_LO", BITS(fetch_word(asic, stream, 1), 3, 32), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "COMPARE_ADDR_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 16, ib_vmid, "MASK_LO", fetch_word(asic, stream, 3), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 20, ib_vmid, "MASK_HI", fetch_word(asic, stream, 4), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 24, ib_vmid, "REFERENCE_LO", fetch_word(asic, stream, 5), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 28, ib_vmid, "REFERENCE_HI", fetch_word(asic, stream, 6), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 32, ib_vmid, "IB_BASE1_LO", BITS(fetch_word(asic, stream, 7), 2, 32), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 36, ib_vmid, "IB_BASE1_HI", fetch_word(asic, stream, 8), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 40, ib_vmid, "IB_SIZE1", BITS(fetch_word(asic, stream, 9), 0, 20), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 40, ib_vmid, "TEMPORAL1", BITS(fetch_word(asic, stream, 9), 28, 30), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 44, ib_vmid, "IB_BASE2_LO", BITS(fetch_word(asic, stream, 10), 2, 32), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 48, ib_vmid, "IB_BASE2_HI", fetch_word(asic, stream, 11), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 52, ib_vmid, "IB_SIZE2", BITS(fetch_word(asic, stream, 12), 0, 20), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 52, ib_vmid, "TEMPORAL2", BITS(fetch_word(asic, stream, 12), 28, 30), NULL, 10, 32);
+			} else {
+				// not COND packet
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "IB_BASE_LO", BITS(fetch_word(asic, stream, 0), 2, 32) << 2, NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "SWAP", BITS(fetch_word(asic, stream, 0), 0, 2), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "IB_BASE_HI", BITS(fetch_word(asic, stream, 1), 0, 16), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "IB_SIZE", BITS(fetch_word(asic, stream, 2), 0, 20), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "IB_VMID", BITS(fetch_word(asic, stream, 2), 24, 28), NULL, 10, 32);
+				if (asic->family >= FAMILY_AI) {
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "CHAIN", BITS(fetch_word(asic, stream, 2), 20, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "PRE_ENA", BITS(fetch_word(asic, stream, 2), 21, 22), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "TEMPORAL", BITS(fetch_word(asic, stream, 2), 28, 30), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "PRE_RESUME", BITS(fetch_word(asic, stream, 2), 30, 31), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "PRIV", BITS(fetch_word(asic, stream, 2), 31, 32), NULL, 10, 32);
+				}
+			}
+			break;
+		case 0x37: // WRITE_DATA
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE", BITS(fetch_word(asic, stream, 0), 30, 32), op_37_engines[BITS(fetch_word(asic, stream, 0), 30, 32)], 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "AID_ID", BITS(fetch_word(asic, stream, 0), 23, 25), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "WR_CONFIRM", BITS(fetch_word(asic, stream, 0), 20, 21), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "WR_ONE_ADDR", BITS(fetch_word(asic, stream, 0), 16, 17), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_SEL", BITS(fetch_word(asic, stream, 0), 8, 12), op_37_dst_sel[BITS(fetch_word(asic, stream, 0), 8, 12)],  10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_LO", BITS(fetch_word(asic, stream, 1), 2, 32) << 2, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "DST_ADDR_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+			if (BITS(fetch_word(asic, stream, 0), 8, 12) == 0) { // mem-mapped reg
+				uint32_t n;
+				uint64_t reg_addr = ((uint64_t)fetch_word(asic, stream, 2) << 32) | fetch_word(asic, stream, 1);
+				for (n = 3; n < stream->n_words; n++) {
+					ui->add_field(ui, ib_addr + 16 + (n - 3) * 4, ib_vmid, umr_reg_name(asic, reg_addr), fetch_word(asic, stream, n), NULL, 16, 32);
+					reg_addr += 1;
+				}
+			}
+			break;
+		case 0x3C: // WAIT_REG_MEM
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE", BITS(fetch_word(asic, stream, 0), 8, 9), BITS(fetch_word(asic, stream, 0), 8, 9) ? "PFP" : "ME", 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "MEMSPACE", BITS(fetch_word(asic, stream, 0), 4, 5), BITS(fetch_word(asic, stream, 0), 4, 5) ? "MEM" : "REG", 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "OPERATION", BITS(fetch_word(asic, stream, 0), 6, 8), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "FUNCTION", BITS(fetch_word(asic, stream, 0), 0, 4), op_3c_functions[BITS(fetch_word(asic, stream, 0), 0, 4)], 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "MES_INTR_PIPE", BITS(fetch_word(asic, stream, 0), 22, 24), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "MES_ACTION", BITS(fetch_word(asic, stream, 0), 24, 25), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "POLL_ADDRESS_LO", BITS(fetch_word(asic, stream, 1), 2, 32) << 2, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "SWAP", BITS(fetch_word(asic, stream, 1), 0, 2), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "POLL_ADDRESS_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "REFERENCE", fetch_word(asic, stream, 3), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "MASK", fetch_word(asic, stream, 4), NULL, 16, 32);
+// TODO: should this be 15:0 for gen12
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "POLL INTERVAL", fetch_word(asic, stream, 5), NULL, 16, 32);
+			break;
+		case 0x40: // PKT3_COPY_DATA
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_SEL", BITS(fetch_word(asic, stream, 0), 0, 4), op_40_mem_sel[BITS(fetch_word(asic, stream, 0), 0, 4)], 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_SEL", BITS(fetch_word(asic, stream, 0), 8, 12), op_40_mem_sel[BITS(fetch_word(asic, stream, 0), 8, 12)], 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_TEMPORAL", BITS(fetch_word(asic, stream, 0), 13, 15), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "COUNT_SEL", BITS(fetch_word(asic, stream, 0), 16, 17), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "WR_CONFIRM", BITS(fetch_word(asic, stream, 0), 20, 21), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "PQ_EXE_STATUS", BITS(fetch_word(asic, stream, 0), 29, 30), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 30, 32), NULL, 10, 32);
+
+			switch (BITS(fetch_word(asic, stream, 0), 0, 4)) {
+				case 0: ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_REG_OFFSET", BITS(fetch_word(asic, stream, 1), 0, 18), umr_reg_name(asic, BITS(fetch_word(asic, stream, 1), 0, 18)), 16, 32); break;
+				case 5: ui->add_field(ui, ib_addr + 8, ib_vmid, "IMM_DATA", fetch_word(asic, stream, 1), NULL, 16, 32); break;
+				default: ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_LO", BITS(fetch_word(asic, stream, 1), 2, 32) << 2, NULL, 16, 32); break;
+			}
+
+			if (BITS(fetch_word(asic, stream, 0), 0, 4) == 5 && BITS(fetch_word(asic, stream, 0), 16, 17) == 1)
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "IMM_DATA_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+			else
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_DATA_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+
+			switch (BITS(fetch_word(asic, stream, 0), 0, 4)) {
+				case 0: ui->add_field(ui, ib_addr + 16, ib_vmid, "DST_REG_OFFSET", BITS(fetch_word(asic, stream, 3), 0, 18), umr_reg_name(asic, BITS(fetch_word(asic, stream, 3), 0, 18)), 16, 32); break;
+				default: ui->add_field(ui, ib_addr + 16, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 3), NULL, 16, 32); break;
+			}
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "DST_ADDR_HI", fetch_word(asic, stream, 4), NULL, 16, 32);
+			break;
+		case 0x46: // EVENT_WRITE
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_TYPE", BITS(fetch_word(asic, stream, 0), 0, 6), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_INDEX", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
+			if (stream->n_words > 2) {
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDRESS_LO", BITS(fetch_word(asic, stream, 1), 3, 32) << 3, NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 12, ib_vmid, "ADDRESS_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+			}
+			break;
+		case 0x47: // EVENT_WRITE_EOP
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_TYPE", BITS(fetch_word(asic, stream, 0), 0, 6), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_INDEX", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2", BITS(fetch_word(asic, stream, 0), 20, 21), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDRESS_LO", BITS(fetch_word(asic, stream, 1), 2, 32) << 2, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "ADDRESS_HI", BITS(fetch_word(asic, stream, 2), 0, 16), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "DATA_SEL", BITS(fetch_word(asic, stream, 2), 29, 32), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "INT_SEL", BITS(fetch_word(asic, stream, 2), 24, 26), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "DATA_LO", fetch_word(asic, stream, 3), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "DATA_HI", fetch_word(asic, stream, 4), NULL, 16, 32);
+			break;
+		case 0x49: // RELEASE_MEM
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_TYPE", BITS(fetch_word(asic, stream, 0), 0, 6), vgt_event_decode(BITS(fetch_word(asic, stream, 0), 0, 6)), 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EVENT_INDEX", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "GCR_CNTL", BITS(fetch_word(asic, stream, 0), 12, 24), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "EXECUTE", BITS(fetch_word(asic, stream, 0), 28, 29), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "GLK_INV", BITS(fetch_word(asic, stream, 0), 30, 31), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "PWS_ENABLE", BITS(fetch_word(asic, stream, 0), 31, 32), NULL, 10, 32);
+
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_SEL", BITS(fetch_word(asic, stream, 1), 16, 18), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "MES_INTR_PIPE", BITS(fetch_word(asic, stream, 1), 20, 22), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "MES_ACTION_ID", BITS(fetch_word(asic, stream, 1), 22, 24), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "INT_SEL", BITS(fetch_word(asic, stream, 1), 24, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "DATA_SEL", BITS(fetch_word(asic, stream, 1), 29, 32), NULL, 10, 32);
+
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "ADDR_LO", fetch_word(asic, stream, 2), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "ADDR_HI", fetch_word(asic, stream, 3), NULL, 16, 32);
+
+			if (BITS(fetch_word(asic, stream, 1), 24, 27) == 5 ||
+			    BITS(fetch_word(asic, stream, 1), 24, 27) == 6) {
+				ui->add_field(ui, ib_addr + 20, ib_vmid, "CMP_DATA_LO", fetch_word(asic, stream, 4), NULL, 16, 32);
+			} else if (BITS(fetch_word(asic, stream, 1), 29, 32) == 5) {
+				ui->add_field(ui, ib_addr + 20, ib_vmid, "DW_OFFSET", BITS(fetch_word(asic, stream, 4), 0, 16), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 20, ib_vmid, "NUM_WORDS", BITS(fetch_word(asic, stream, 4), 16, 32), NULL, 10, 32);
+			} else {
+				ui->add_field(ui, ib_addr + 20, ib_vmid, "DATA_LO", fetch_word(asic, stream, 4), NULL, 16, 32);
+			}
+
+			if (BITS(fetch_word(asic, stream, 1), 24, 27) == 5 ||
+			    BITS(fetch_word(asic, stream, 1), 24, 27) == 6)
+				ui->add_field(ui, ib_addr + 24, ib_vmid, "CMP_DATA_HI", fetch_word(asic, stream, 5), NULL, 16, 32);
+			else
+				ui->add_field(ui, ib_addr + 24, ib_vmid, "DATA_HI", fetch_word(asic, stream, 5), NULL, 16, 32);
+
+			ui->add_field(ui, ib_addr + 28, ib_vmid, "INT_CTXID", fetch_word(asic, stream, 6), NULL, 16, 32);
+			break;
+		case 0x4D: // DISPATCH_TASKMESH_GFX
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "XYZ_DIM_LOC", BITS(fetch_word(asic, stream, 0), 0, 16), umr_reg_name(asic, BITS(fetch_word(asic, stream, 0), 0, 16) + 0x2C00), 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "RING_ENTRY_LOC", BITS(fetch_word(asic, stream, 0), 16, 32), umr_reg_name(asic, BITS(fetch_word(asic, stream, 0), 16, 32) + 0x2C00), 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "THREAD_TRACE_MARKER_ENABLE", BITS(fetch_word(asic, stream, 1), 31, 32), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "XYZ_DIM_ENABLE", BITS(fetch_word(asic, stream, 1), 30, 31), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "MODE1_ENABLE", BITS(fetch_word(asic, stream, 1), 29, 30), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "LINEAR_DISPATCH_ENABLE", BITS(fetch_word(asic, stream, 1), 28, 29), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "DRAW_INITIATOR", fetch_word(asic, stream, 2), NULL, 16, 32);
+			break;
+		case 0x50: // DMA_DATA
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 0, 1), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_INDIRECT", BITS(fetch_word(asic, stream, 0), 1, 2), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_INDIRECT", BITS(fetch_word(asic, stream, 0), 2, 3), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_TEMPORAL", BITS(fetch_word(asic, stream, 0), 13, 15), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_SEL", BITS(fetch_word(asic, stream, 0), 20, 22), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_SEL", BITS(fetch_word(asic, stream, 0), 29, 31), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "CP_SYNC", BITS(fetch_word(asic, stream, 0), 31, 32), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_LO_OR_DATA", fetch_word(asic, stream, 1), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_ADDR_HI", fetch_word(asic, stream, 2), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 3), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "DST_ADDR_HI", fetch_word(asic, stream, 4), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "BYTE_COUNT", BITS(fetch_word(asic, stream, 5), 0, 26), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "SAS", BITS(fetch_word(asic, stream, 5), 26, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "DAS", BITS(fetch_word(asic, stream, 5), 27, 28), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "SAIC", BITS(fetch_word(asic, stream, 5), 28, 29), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "DAIC", BITS(fetch_word(asic, stream, 5), 29, 30), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "RAW_WAIT", BITS(fetch_word(asic, stream, 5), 30, 31), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "DIS_WC", BITS(fetch_word(asic, stream, 5), 31, 32), NULL, 10, 32);
+			break;
+		case 0x9A: // DMA_DATA_FILL_MULTI
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 0, 1), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "MEMLOG_CLEAR", BITS(fetch_word(asic, stream, 0), 10, 11), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_SEL", BITS(fetch_word(asic, stream, 0), 20, 22), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_TEMPORAL", BITS(fetch_word(asic, stream, 0), 25, 27), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_SEL", BITS(fetch_word(asic, stream, 0), 29, 31), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "CP_SYNC", BITS(fetch_word(asic, stream, 0), 31, 32), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "BYTE_STRIDE", fetch_word(asic, stream, 1), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "DMA_COUNT", fetch_word(asic, stream, 2), NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 3), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "DST_ADDR_HI", fetch_word(asic, stream, 4), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "BYTE_COUNT", BITS(fetch_word(asic, stream, 5), 0, 26), NULL, 10, 32);
+			break;
+		case 0xA2: // PKT3_MAP_QUEUES
+			{ uint32_t ext_sel = BITS(fetch_word(asic, stream, 0), 2, 4),
+					   engine_sel = BITS(fetch_word(asic, stream, 0), 26, 29);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "EXT_ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 2, 4), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_SEL", BITS(fetch_word(asic, stream, 0), 4, 6), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "VMID", BITS(fetch_word(asic, stream, 0), 8, 12), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "GWS_ENABLED", BITS(fetch_word(asic, stream, 0), 12, 13), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_ID", BITS(fetch_word(asic, stream, 0), 13, 16), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "PIPE_ID", BITS(fetch_word(asic, stream, 0), 16, 18), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "ME_ID", BITS(fetch_word(asic, stream, 0), 18, 20), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_TYPE", BITS(fetch_word(asic, stream, 0), 21, 24), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "STATIC_QUEUE_GROUP", BITS(fetch_word(asic, stream, 0), 24, 26), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 26, 29), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "NUM_QUEUES", BITS(fetch_word(asic, stream, 0), 29, 32), NULL, 10, 32);
+
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "CHECK_DISABLE", BITS(fetch_word(asic, stream, 1), 1, 2), NULL, 16, 32);
+				ui->add_field(ui, ib_addr + 8, ib_vmid, "DOORBELL_OFFSET", BITS(fetch_word(asic, stream, 1), 2, 28), NULL, 16, 32);
+				{
+					uint32_t n;
+					for (n = 2; n + 4 <= stream->n_words; n += 4) {
+						ui->add_field(ui, ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_LO", fetch_word(asic, stream, n), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 16 + 16 * ((n - 2) / 4), ib_vmid, "MQD_ADDR_HI", fetch_word(asic, stream, n + 1), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 20 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_LO", fetch_word(asic, stream, n + 2), NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 24 + 16 * ((n - 2) / 4), ib_vmid, "WPTR_ADDR_HI", fetch_word(asic, stream, n + 3), NULL, 16, 32);
+						if (ui->add_data)
+							ui->add_data(ui, asic,
+										 ib_addr + 12 + 16 * ((n - 2) / 4), ib_vmid,
+										 ((uint64_t)fetch_word(asic, stream, n)) | (((uint64_t)fetch_word(asic, stream, n + 1)) << 32), BITS(fetch_word(asic, stream, 0), 8, 12),
+										 UMR_DATABLOCK_MQD_NV, ext_sel == 0 ? engine_sel : 2);
+					}
+				}
+			}
+			break;
+		case 0xA3: // PKT3_UNMAP_QUEUES
+			{
+				uint32_t action, queue_sel, num_queues, engine_sel;
+
+				queue_sel = BITS(fetch_word(asic, stream, 0), 4, 6);
+				engine_sel = BITS(fetch_word(asic, stream, 0), 26, 29);
+				num_queues = BITS(fetch_word(asic, stream, 0), 29, 32);
+				action = BITS(fetch_word(asic, stream, 0), 0, 2);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "ACTION", BITS(fetch_word(asic, stream, 0), 0, 2), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "QUEUE_SEL", queue_sel, NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "ENGINE_SEL", engine_sel, NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "EXT_ENGINE_SEL", BITS(fetch_word(asic, stream, 0), 2, 4), NULL, 10, 32);
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "NUM_QUEUES", num_queues, NULL, 10, 32);
+				if (queue_sel == 1)
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "PASID", BITS(fetch_word(asic, stream, 1), 0, 16), NULL, 10, 32);
+				else
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DOORBELL_OFFSET0", BITS(fetch_word(asic, stream, 1), 2, 28), NULL, 16, 32);
+				if (action == 3)
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "TF_ADDR_LO32", BITS(fetch_word(asic, stream, 2), 2, 32), NULL, 16, 32);
+				else
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DOORBELL_OFFSET1", BITS(fetch_word(asic, stream, 2), 2, 28), NULL, 16, 32);
+				if (action == 3)
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "TF_ADDR_HI32", BITS(fetch_word(asic, stream, 3), 0, 32), NULL, 16, 32);
+				else
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "DOORBELL_OFFSET2", BITS(fetch_word(asic, stream, 3), 2, 28), NULL, 16, 32);
+				if (action == 3)
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "TF_DATA", BITS(fetch_word(asic, stream, 4), 0, 32), NULL, 16, 32);
+				else
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "DOORBELL_OFFSET3", BITS(fetch_word(asic, stream, 4), 2, 28), NULL, 16, 32);
+			}
+			break;
+		case 0xB8: // SET_CONTEXT_REG_PAIRS
+		case 0xBA: // SET_SH_REG_PAIRS
+		case 0xBE: // SET_UCONFIG_REG_PAIRS
+			{
+				uint32_t offset, n, m;
+
+				switch (stream->opcode) {
+					case 0xB8: offset = 0xA000; break;
+					case 0xBA: offset = 0x2C00; break;
+					case 0xBE: offset = 0xC000; break;
+				}
+
+				for (m = n = 0; n < stream->n_words; n += 2, ++m) {
+					ui->add_field(ui, ib_addr + 4 + 8 * m, ib_vmid, "REG_OFFSET", BITS(fetch_word(asic, stream, n+0), 0, 16), umr_reg_name(asic, offset + BITS(fetch_word(asic, stream, n+0), 0, 16)), 16, 32);
+					ui->add_field(ui, ib_addr + 8 + 8 * m, ib_vmid, "REG_DATA", fetch_word(asic, stream, n+1), NULL, 16, 32);
+				}
+			}
+			break;
+		case 0xB9: // SET_CONTEXT_REG_PAIRS_PACKED
+		case 0xBC:
+		case 0xBD: // SET_SH_REG_PAIRS_PACKED(_N)
+			{
+				uint32_t offset, n, m;
+
+				switch (stream->opcode) {
+					case 0xB9: offset = 0xA000; break;
+					case 0xBC:
+					case 0xBD: offset = 0x2C00; break;
+				}
+
+				ui->add_field(ui, ib_addr + 4, ib_vmid, "REG_WRITES_COUNT", BITS(fetch_word(asic, stream, 0), 0, 16), NULL, 10, 32);
+
+				for (m = 0, n = 1; n < stream->n_words; n += 3, ++m) {
+					ui->add_field(ui, ib_addr + 8 + 12 * m, ib_vmid, "REG_OFFSET0", BITS(fetch_word(asic, stream, n+0), 0, 16), umr_reg_name(asic, offset + BITS(fetch_word(asic, stream, n+0), 0, 16)), 16, 32);
+					ui->add_field(ui, ib_addr + 8 + 12 * m, ib_vmid, "REG_OFFSET1", BITS(fetch_word(asic, stream, n+0), 16, 32), umr_reg_name(asic, offset + BITS(fetch_word(asic, stream, n+0), 16, 32)), 16, 32);
+					ui->add_field(ui, ib_addr + 12 + 12 * m, ib_vmid, "REG_DATA0", fetch_word(asic, stream, n+1), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16 + 12 * m, ib_vmid, "REG_DATA1", fetch_word(asic, stream, n+2), NULL, 16, 32);
+				}
+			}
+			break;
+		default:
+			decode_pkt3_gfx11(asic, ui, stream, ib_addr, ib_vmid);
+			break;
+	}
+}
 
 static void decode_pkt3(struct umr_asic *asic, struct umr_stream_decode_ui *ui, struct umr_pm4_stream *stream, uint64_t ib_addr, uint32_t ib_vmid)
 {
@@ -1700,6 +2017,7 @@ static void decode_pkt3(struct umr_asic *asic, struct umr_stream_decode_ui *ui,
 		case 9: decode_pkt3_gfx9(asic, ui, stream, ib_addr, ib_vmid); break;
 		case 10: decode_pkt3_gfx10(asic, ui, stream, ib_addr, ib_vmid); break;
 		case 11: decode_pkt3_gfx11(asic, ui, stream, ib_addr, ib_vmid); break;
+		case 12: decode_pkt3_gfx12(asic, ui, stream, ib_addr, ib_vmid); break;
 		default:
 			asic->err_msg("[BUG]: GFX maj (%d) not supported in decode_pkt3()\n", maj);
 			return;
diff --git a/src/lib/read_mes_stream.c b/src/lib/read_mes_stream.c
index 38f5ec912ee66ce15247fbb53aabe7de97e600c2..657205e194c74955848f300aeeb5a283fadc290d 100644
--- a/src/lib/read_mes_stream.c
+++ b/src/lib/read_mes_stream.c
@@ -42,8 +42,8 @@ static const char *mes_v10_opcodes[] = {
 /* 0E */	"MES_SCH_API_MISC",
 /* 0F */	"MES_SCH_API_UPDATE_ROOT_PAGE_TABLE",
 /* 10 */	"MES_SCH_API_AMD_LOG",
-/* 11 */	"UNK",
-/* 12 */	"UNK",
+/* 11 */	"MES_SCH_API_SET_SE_MODE",
+/* 12 */	"MES_SCH_API_SET_GANG_SUBMIT",
 /* 13 */	"MES_SCH_API_SET_HW_RSRC_1",
 };
 
@@ -60,6 +60,8 @@ static char *mes_v11_misc_api_opcodes[] = {
 	"READ_REG",
 	"WAIT_REG_MEM",
 	"SET_SHADER_DEBUGGER",
+	"NOTIFY_WORK_ON_UNMAPPED_QUEUE",
+	"NOTIFY_TO_UNMAP_PROCESSES",
 };
 
 static char *mes_v11_wrm_operation[] = {
@@ -89,6 +91,18 @@ static char *mes_v10_add_queue_priority_level[] = {
 	"REALTIME",
 };
 
+static char *mes_v12_set_se_mode[] = {
+	"INVALID",
+	"SINGLE_SE",
+	"DUAL_SE",
+	"LOWER_POWER",
+};
+
+static char *mes_v12_query_mes_subopcode[] = {
+	"GET_CTX_ARRAY_SIZE",
+	"CHECK_HEALTHY",
+};
+
 #define STR_LOOKUP(str_lut, idx, default) \
 	((idx) < sizeof(str_lut) / sizeof(str_lut[0]) ? str_lut[(idx)] : (default))
 
@@ -112,6 +126,8 @@ struct umr_mes_stream *umr_mes_decode_stream(struct umr_asic *asic, uint32_t *st
 		mes_ver_maj = 10;
 	} else if (ip->discoverable.maj == 11) {
 		mes_ver_maj = 11;
+	} else if (ip->discoverable.maj == 12) {
+		mes_ver_maj = 12;
 	}
 
 	if (!mes_ver_maj) {
@@ -189,10 +205,11 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 			MAX_GFX_PIPES,
 			MAX_SDMA_PIPES,
 			PRIORITY_NUM_LEVELS,
-			MAX_HWIP_SEGMENT;
+			MAX_HWIP_SEGMENT,
+			MISC_DATA_MAX_SIZE_IN_DWORDS;
 	} params;
         struct umr_ip_block *ip;
-	int mes_ver_maj;
+	int mes_ver_maj, pack8 = 0;
 	const char* opcode_name;
 
 	ip = umr_find_ip_block(asic, "gfx", asic->options.vm_partition);
@@ -201,10 +218,13 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 		return NULL;
 	}
 
-        if (ip->discoverable.maj == 10 && ip->discoverable.min >= 1) {
+    if (ip->discoverable.maj == 10 && ip->discoverable.min >= 1) {
 		mes_ver_maj = 10;
 	} else if (ip->discoverable.maj == 11) {
 		mes_ver_maj = 11;
+	} else if (ip->discoverable.maj == 12) {
+		mes_ver_maj = 12;
+		pack8 = 1; // MESv12 uses 8-byte packed structs instead of 4-byte packed
 	} else {
 		asic->err_msg("[ERROR]: MES decoding not supported on this ASIC\n");
 		return NULL;
@@ -214,6 +234,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 	params.MAX_GFX_PIPES = 2;
 	params.MAX_SDMA_PIPES = 2;
 	params.PRIORITY_NUM_LEVELS = 5;
+	params.MISC_DATA_MAX_SIZE_IN_DWORDS = 20;
 	if (mes_ver_maj == 10) {
 		params.MAX_HWIP_SEGMENT = 6;
 	} else {
@@ -250,6 +271,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 					sprintf(tmpfieldname, "aggregated_doorbells[%" PRIu32 "]", j);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, tmpfieldname, fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				}
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "g_sch_ctx_gpu_mc_ptr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "query_status_fence_gpu_mc_ptr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				for (j = 0; j < params.MAX_HWIP_SEGMENT; j++ ) {
@@ -264,6 +286,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 					sprintf(tmpfieldname, "osssys_base[%" PRIu32 "]", j);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, tmpfieldname, fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				}
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 
@@ -274,23 +297,39 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "apply_grbm_remote_register_dummy_read_wa", (fetch_word(asic, stream, i) >> 4) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "second_gfx_pipe_enabled", (fetch_word(asic, stream, i) >> 5) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "enable_level_process_quantum_check", (fetch_word(asic, stream, i) >> 6) & 1, NULL, 10, 32);
+
 				if (mes_ver_maj == 10) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "apply_cwsr_program_all_vmid_sq_shader_tba_registers_wa", (fetch_word(asic, stream, i) >> 7) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "enable_mqd_active_poll", (fetch_word(asic, stream, i) >> 8) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "disable_timer_int", (fetch_word(asic, stream, i) >> 9) & 1, NULL, 10, 32);
+				} else if (mes_ver_maj >= 11) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "legacy_sch_mode", (fetch_word(asic, stream, i) >> 7) & 1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "disable_add_queue_wptr_mc_addr", (fetch_word(asic, stream, i) >> 8) & 1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "enable_mes_event_int_logging", (fetch_word(asic, stream, i) >> 9) & 1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "enable_reg_active_poll", (fetch_word(asic, stream, i) >> 10) & 1, NULL, 10, 32);
+					if (mes_ver_maj == 12) {
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "use_disable_queue_in_legacy_uq_preemption", (fetch_word(asic, stream, i) >> 11) & 1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "send_write_data", (fetch_word(asic, stream, i) >> 12) & 1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "os_tdr_timeout_override", (fetch_word(asic, stream, i) >> 13) & 1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "use_rs64mem_for_proc_gang_ctx", (fetch_word(asic, stream, i) >> 14) & 1, NULL, 10, 32);
+					}
 				}
 				++i;
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "overscubscription_timer", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_info", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
-				}
-				// NOTE: this extra if will make sense later.
-				if (mes_ver_maj == 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "event_intr_history_gpu_mc_ptr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				}
+				if (mes_ver_maj == 12) {
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "os_tdr_timeout_in_sec", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 1: // MES_SCH_API_SET_SCHEDULING_CONFIG
+				if (pack8 && !(i&1)) ++i;
 				for (j = 0; j < params.PRIORITY_NUM_LEVELS; j++ ) {
 					sprintf(tmpfieldname, "grace_period_other_levels[%" PRIu32 "]", j);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, tmpfieldname, (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
@@ -304,12 +343,17 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, tmpfieldname, (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				}
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "normal_yield_percent", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				}
 				break;
 
 			case 2: // MESAPI__ADD_QUEUE
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "page_table_base_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_va_start", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_va_end", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
@@ -321,8 +365,8 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 
 // todo: guessing what size an enum is...
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_global_priority_level", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_priority_level, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
-
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mqd_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "wptr_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "h_context", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
@@ -336,6 +380,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_base", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_size", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "oa_mask", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "trap_handler_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "vm_context_cntl", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 
@@ -345,7 +390,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_gang_suspended", (fetch_word(asic, stream, i) >> 6) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_tmz_queue", (fetch_word(asic, stream, i) >> 7) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "map_kiq_utility_queue", (fetch_word(asic, stream, i) >> 8) & 1, NULL, 10, 32);
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_kfd_process", (fetch_word(asic, stream, i) >> 9) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "trap_en", (fetch_word(asic, stream, i) >> 10) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_aql_queue", (fetch_word(asic, stream, i) >> 11) & 1, NULL, 10, 32);
@@ -355,154 +400,248 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_long_running", (fetch_word(asic, stream, i) >> 15) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_dwm_queue", (fetch_word(asic, stream, i) >> 16) & 1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "is_video_blit_queue", (fetch_word(asic, stream, i) >> 17) & 1, NULL, 10, 32);
-
 				}
 				++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "tma_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "sch_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "pipe_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "alignment_mode_setting", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "unmap_flag_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				}
 				break;
 
 			case 3: // MESAPI__REMOVE_QUEUE
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
-				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "unmap_legacy_gfx_queue", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32);
+				if (mes_ver_maj < 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "unmap_legacy_gfx_queue", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32);
+				}
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "unmap_kiq_utility_queue", (fetch_word(asic, stream, i) >> 1) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "preempt_legacy_gfx_queue", (fetch_word(asic, stream, i) >> 2) & 1, NULL, 10, 32);
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "unmap_legacy_queue", (fetch_word(asic, stream, i) >> 3) & 1, NULL, 10, 32);
 				}
 				++i;
-
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "pipe_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "tf_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "tf_data", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 
 // todo: guessing what size an enum is...
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_type", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_type, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
 				}
+				if (mes_ver_maj == 12) {
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 4: //MESAPI__PERFORM_YIELD
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "dummy", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				}
 				break;
 
-			case 5: // SET_GANG_PRIOR
-// TODO: I don't see a struct for this in the header
+			case 5: // SET_GANG_PRIORITY_LEVEL
+				// What structure is this?
 				break;
 
 			case 6: // MESAPI__SUSPEND
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "suspend_all_gangs", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "suspend_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "suspend_fence_value", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "sch_id", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "legacy_uq_type", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_type, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "legacy_uq_priority_level", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_priority_level, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 7: // MESAPI__RESUME
-				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "suspend_all_gangs", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32); ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "resume_all_gangs", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 8: // MESAPI__RESET
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reset_queue_only", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "hang_detect_then_reset", (fetch_word(asic, stream, i) >> 1) & 1, NULL, 10, 32);
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "hang_detect_only", (fetch_word(asic, stream, i) >> 2) & 1, NULL, 10, 32);
-				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reset_legacy_gfx", (fetch_word(asic, stream, i) >> 3) & 1, NULL, 10, 32); ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reset_legacy_gfx", (fetch_word(asic, stream, i) >> 3) & 1, NULL, 10, 32);
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "use_connected_queue_index", (fetch_word(asic, stream, i) >> 4) & 1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "use_connected_queue_index_p1", (fetch_word(asic, stream, i) >> 5) & 1, NULL, 10, 32);
+				}
+				++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 // todo: guessing what size an enum is
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_type", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_type, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
-
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "pipe_id_lp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_id_lp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "vmid_ip_lp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mqd_mc_addr_lp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset_lp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "wptr_addr_lp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "pipe_id_hp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_id_hp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "vmid_ip_hp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mqd_mc_addr_hp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset_hp", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "wptr_addr_hp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "active_vmids", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "connected_queue_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "connected_queue_index_p1", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 9: //MESAPI__SET_LOGGING_BUFFER
 // todo: guessing what size an enum is
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_type", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_type, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
 
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "logging_buffer_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "number_of_entries", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "interrupt_entry", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "vmid", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 10: //MESAPI__CHANGE_GANG_PRIORITY_LEVEL
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "inprocess_gang_priority", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 // todo: guessing what size an enum is...
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_global_priority_level", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_priority_level, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_quantum", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_quantum_scale", (fetch_word(asic, stream, i)) & 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_quantum_duration", (fetch_word(asic, stream, i) >> 2) & 0xFF, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "apply_quantum_all_processes", (fetch_word(asic, stream, i) >> 10) & 1, NULL, 16, 32);
+					++i;
+				}
 				break;
 
 			case 11: // MESAPI__QUERY_MES_STATUS
-// todo: guessing what size a bool is...
-				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mes_healthy", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
-
+			{
+				uint32_t subopcode;
+				if (mes_ver_maj < 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mes_healthy", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				} else {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "subopcode", subopcode = fetch_word(asic, stream, i), STR_LOOKUP(mes_v12_query_mes_subopcode, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+				}
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					switch (subopcode) {
+						case 0: // QUERY_MES__GET_CTX_ARRAY_SIZE
+							if (pack8 && !(i&1)) ++i;
+							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "proc_ctx_array_size_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_ctx_array_size_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+							break;
+						case 1: // QUERY_MES__CHECK_HEALTHY
+							if (pack8 && !(i&1)) ++i;
+							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "healthy_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+							break;
+					}
+				}
 				break;
+			}
 
 			case 12: // MESAPI__PROGRAM_GDS
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gds_base", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gds_size", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_base", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_size", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "oa_mask", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				break;
 
 			case 13: // MESAPI__SET_DEBUG_VMID
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "use_gds", (fetch_word(asic, stream, i) >> 0) & 1, NULL, 10, 32);
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "operation", (fetch_word(asic, stream, i) >> 1) & 3, STR_LOOKUP(mes_v11_set_debug_opcodes, (fetch_word(asic, stream, i) >> 1) & 3, "UNKNOWN"), 10, 32);
 				}
 				++i;
+
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reserved", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "debug_vmid", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "page_table_base_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_va_start", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
@@ -512,27 +651,36 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_base", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gws_size", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "oa_mask", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
-				if (mes_ver_maj == 11) {
+				if (mes_ver_maj >= 11) {
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "output_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				}
+				if (mes_ver_maj == 12) {
+					if (pack8 && !(i&1)) ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_vm_cntl", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "queue_type", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_add_queue_type, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "alignment_mode_setting", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 14: // MESAPI__MISC (note this changes in v11)
 				if (mes_ver_maj == 10) {
 					uint32_t misc_opcode;
-// todo: enum size...
 					misc_opcode = fetch_word(asic, stream, i);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "opcode", fetch_word(asic, stream, i), STR_LOOKUP(mes_v10_misc_api_opcodes, misc_opcode, "UNKNOWN"), 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 					switch (misc_opcode) {
 						case 0: // MODIFY_REG
-// todo: enum size...
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "subcode", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_value", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							break;
 						case 1: // INV_GART
+							if (pack8 && !(i&1)) ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "inv_range_va_start", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "inv_range_size", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 							break;
@@ -541,19 +689,21 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 							break;
 					}
 					break;
-				} else if (mes_ver_maj == 11) {
-					uint32_t misc_opcode;
-// todo: enum size...
+				} else if (mes_ver_maj >= 11) {
+					uint32_t misc_opcode, j;
 					misc_opcode = fetch_word(asic, stream, i);
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "opcode", fetch_word(asic, stream, i), STR_LOOKUP(mes_v11_misc_api_opcodes, misc_opcode, "UNKNOWN"), 16, 32); ++i;
+					if (pack8 && !(i&1)) ++i;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					j = i;
 					switch (misc_opcode) {
 						case 0: // WRITE_REG
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_value", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							break;
 						case 1: // INV_GART
+							if (pack8 && !(i&1)) ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "inv_range_va_start", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "inv_range_size", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 							break;
@@ -562,10 +712,15 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 							break;
 						case 3: // READ_REG
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+							if (pack8 && !(i&1)) ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "buffer_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+							if (mes_ver_maj == 12) {
+								ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "read64Bits", (fetch_word(asic, stream, i)) & 1, NULL, 16, 32);
+								++i;
+								ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "all", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+							}
 							break;
 						case 4: // WAIT_REG_MEM
-// todo: enum size...
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "op", fetch_word(asic, stream, i), STR_LOOKUP(mes_v11_wrm_operation, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reference", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mask", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
@@ -573,6 +728,7 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "reg_offset2", fetch_word(asic, stream, i), umr_reg_name(asic, fetch_word(asic, stream, i)), 16, 32); ++i;
 							break;
 						case 5: // SET_SHADER_DEBUGGER
+							if (pack8 && !(i&1)) ++i;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "single_memop", fetch_word(asic, stream, i) & 1, NULL, 16, 32);
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "single_alu_op", (fetch_word(asic, stream, i) & 2) >> 1, NULL, 16, 32);
@@ -585,28 +741,69 @@ struct umr_mes_stream *umr_mes_decode_stream_opcodes(struct umr_asic *asic, stru
 							ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "trap_en", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 							break;
 					}
+					// if >= 12 set i to j + MISC_DATA_MAX_SIZE_IN_DWORDS
+					if (mes_ver_maj == 12) {
+						i = j + params.MISC_DATA_MAX_SIZE_IN_DWORDS;
+						if (pack8 && !(i&1)) ++i;
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "doorbell_offset", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+						ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "os_fence", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+					}
 				}
 				break;
 			case 15: // MESAPI__UPDATE_ROOT_PAGE_TABLE
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "page_table_base_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "process_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				}
 				break;
 
 			case 16: // MESAPI_AMD_LOG
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "p_buffer_memory", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "p_buffer_size_used", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				if (mes_ver_maj == 12) {
+					ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				}
+				break;
+
+			case 17: // MESAPI__SET_SE_MODE
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "new_se_mode", fetch_word(asic, stream, i), STR_LOOKUP(mes_v12_set_se_mode, fetch_word(asic, stream, i), "UNKNOWN"), 16, 32); ++i;
+				if (pack8 && !(i&1)) ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "cpg_ctxt_sync_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "cpg_ctxt_sync_fence_value", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "log_seq_time", (fetch_word(asic, stream, i)) & 1, NULL, 16, 32);
+				++i;
+				if (pack8 && !(i&1)) ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				break;
+
+			case 18: // MESAPI__SET_GANG_SUBMIT
+				if (pack8 && !(i&1)) ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "slave_gang_context_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
+				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "slave_gang_context_array_index", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				break;
 
 			case 19: // MES_SCH_API_SET_HW_RSRC_1
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "api_completion_fence_value", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "timestamp", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "enable_mes_info_ctx", BITS(fetch_word(asic, stream, i), 0, 1), NULL, 16, 32);
 				++i;
+				if (pack8 && !(i&1)) ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mes_info_ctx_mc_addr", (uint64_t)fetch_word(asic, stream, i) | ((uint64_t)fetch_word(asic, stream, i+1) << 32), NULL, 16, 64); i += 2;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mes_info_ctx_size", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
 				ui->add_field(ui, ib_addr + 4 * i, ib_vmid, "mes_kiq_unmap_timeout", fetch_word(asic, stream, i), NULL, 16, 32); ++i;
diff --git a/src/lib/read_vram.c b/src/lib/read_vram.c
index d574fbbbeec09fb426945442c0b0adf555248a91..607c6126f418feff3ebc7be2b3c79a8a10efd0de 100644
--- a/src/lib/read_vram.c
+++ b/src/lib/read_vram.c
@@ -387,6 +387,17 @@ static pde_fields_t decode_pde_entry(const struct umr_asic *asic, uint64_t pde_e
 			pde_fields.tfs_addr      = (pde_entry >> 57) & 1;
 			pde_fields.llc_noalloc   = (pde_entry >> 58) & 1;
 			break;
+		case 12:
+			pde_fields.frag_size     = (pde_entry >> 58) & 0x1F;
+			pde_fields.pte_base_addr = pde_entry & 0xFFFFFFFFFFC0ULL;
+			pde_fields.valid         = pde_entry & 1;
+			pde_fields.system        = (pde_entry >> 1) & 1;
+			pde_fields.coherent      = (pde_entry >> 2) & 1;
+			pde_fields.pa_rsvd       = (pde_entry >> 48) & 0xF;
+			pde_fields.mall_reuse    = (pde_entry >> 54) & 3;
+			pde_fields.tfs_addr      = (pde_entry >> 56) & 1;
+			pde_fields.pte           = (pde_entry >> 63) & 1;
+			break;
 	}
 	return pde_fields;
 }
@@ -475,6 +486,24 @@ static pte_fields_t decode_pte_entry(const struct umr_asic *asic, uint64_t pte_e
 			pte_fields.llc_noalloc    = (pte_entry >> 58) & 1;
 			is_pde                    = pte_fields.further;
 			break;
+		case 12:
+			pte_fields.valid          = pte_entry & 1;
+			pte_fields.system         = (pte_entry >> 1) & 1;
+			pte_fields.coherent       = (pte_entry >> 2) & 1;
+			pte_fields.tmz            = (pte_entry >> 3) & 1;
+			pte_fields.execute        = (pte_entry >> 4) & 1;
+			pte_fields.read           = (pte_entry >> 5) & 1;
+			pte_fields.write          = (pte_entry >> 6) & 1;
+			pte_fields.fragment       = (pte_entry >> 7) & 0x1F;
+			pte_fields.pa_rsvd        = (pte_entry >> 48) & 0xF;
+			pte_fields.software       = (pte_entry >> 52) & 3;
+			pte_fields.mtype          = (pte_entry >> 54) & 3;
+			pte_fields.prt            = (pte_entry >> 56) & 1;
+			pte_fields.gcr            = (pte_entry >> 57) & 1;
+			pte_fields.dcc            = (pte_entry >> 58) & 1;
+			pte_fields.pte            = (pte_entry >> 63) & 1;
+			is_pde                    = !pte_fields.pte;
+			break;
 	}
 
 	// PTEs hold physical address in 47:12
@@ -543,6 +572,21 @@ static void print_pde_fields(struct umr_asic *asic,
 					pde_fields.tfs_addr,
 					pde_fields.llc_noalloc);
 			break;
+		case 12:
+			asic->mem_funcs.vm_message(
+					", PBA==0x%012" PRIx64 ", V=%" PRIu64
+					", S=%" PRIu64 ", C=%" PRIu64
+					", U=%" PRIu64 ", A=%" PRIu64
+					", FS=%" PRIu64 ", P=%" PRIu64 "\n",
+					pde_fields.pte_base_addr,
+					pde_fields.valid,
+					pde_fields.system,
+					pde_fields.coherent,
+					pde_fields.mall_reuse,
+					pde_fields.tfs_addr,
+					pde_fields.frag_size,
+					pde_fields.pte);
+			break;
 	}
 }
 
@@ -689,6 +733,31 @@ static void print_pte(struct umr_asic *asic,
 					pte_fields.gcr,
 					pte_fields.llc_noalloc);
 			break;
+		case 12:
+			asic->mem_funcs.vm_message("=0x%016" PRIx64 ", VA=0x%012" PRIx64
+					", PBA==0x%012" PRIx64 ", V=%" PRIu64
+					", S=%" PRIu64 ", C=%" PRIu64 ", Z=%" PRIu64
+					", X=%" PRIu64 ", R=%" PRIu64 ", W=%" PRIu64
+					", FS=%" PRIu64 ", SW=%" PRIu64 ", T=%" PRIu64
+					", G=%" PRIu64 ", D=%" PRIu64 ", P=%" PRIu64
+					", MTYPE=",
+					pte_entry,
+					address & va_mask,
+					pte_fields.page_base_addr,
+					pte_fields.valid,
+					pte_fields.system,
+					pte_fields.coherent,
+					pte_fields.tmz,
+					pte_fields.execute,
+					pte_fields.read,
+					pte_fields.write,
+					pte_fields.fragment,
+					pte_fields.software,
+					pte_fields.prt,
+					pte_fields.gcr,
+					pte_fields.dcc,
+					pte_fields.pte);
+			break;
 	}
 
 	switch (pte_fields.mtype) {
@@ -1193,6 +1262,10 @@ pde_is_pte:
 
 			int pte_is_pde = pte_fields.further && pte_fields.valid;
 
+			if (ip->discoverable.maj >= 12 && !pte_fields.pte && pte_fields.valid) {
+				pte_is_pde = 1;
+			}
+
 			if (asic->options.verbose) {
 				if (pte_is_pde) {
 					print_pde(asic, indentation, pde_cnt, page_table_depth, prev_addr,
diff --git a/src/lib/scan_waves.c b/src/lib/scan_waves.c
index 22beacfd78717d2b40aa46062d4e6cf1f865c325..98fab546412a89851ee2996c310366ffd33c0776 100644
--- a/src/lib/scan_waves.c
+++ b/src/lib/scan_waves.c
@@ -249,7 +249,7 @@ static uint32_t wave_read_ind(struct umr_asic *asic, uint32_t simd, uint32_t wav
 	}
 }
 
-static uint32_t wave_read_ind_gfx_10_11(struct umr_asic *asic, uint32_t wave, uint32_t address)
+static uint32_t wave_read_ind_gfx_10_12(struct umr_asic *asic, uint32_t wave, uint32_t address)
 {
 	struct umr_reg *ind_index, *ind_data;
 	uint32_t data;
@@ -303,23 +303,54 @@ int umr_read_wave_status_via_mmio_gfx_10_11(struct umr_asic *asic, uint32_t wave
 	/* type 2 wave data */
 	*no_fields = 0;
 	dst[(*no_fields)++] = (asic->family == FAMILY_GFX11) ? 3 : 2;
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_STATUS")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_LO")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_HI")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_LO")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_HI")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID1")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID2")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_STATUS")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID1")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID2")->addr);
 	if (asic->family < FAMILY_GFX11)
-		dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_INST_DW0")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_GPR_ALLOC")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_LDS_ALLOC")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TRAPSTS")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS2")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_DBG1")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_M0")->addr);
-	dst[(*no_fields)++] = wave_read_ind_gfx_10_11(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_MODE")->addr);
+		dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_INST_DW0")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_GPR_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_LDS_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TRAPSTS")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS2")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_DBG1")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_M0")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_MODE")->addr);
+
+	return 0;
+}
+
+
+int umr_read_wave_status_via_mmio_gfx_12(struct umr_asic *asic, uint32_t wave, uint32_t *dst, int *no_fields)
+{
+	dst[(*no_fields)++] = 4;
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_STATUS")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID1")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID2")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_GPR_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_LDS_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS2")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_DBG1")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_M0")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_MODE")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_STATE_PRIV")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXCP_FLAG_PRIV")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXCP_FLAG_USER")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TRAP_CTRL")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_ACTIVE")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_VALID_AND_IDLE")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_DVGPR_ALLOC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_DVGPR_ALLOC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind_gfx_10_12(asic, wave, umr_find_reg_data(asic, "ixSQ_WAVE_SCHED_MODE")->addr);
 
 	return 0;
 }
@@ -340,6 +371,8 @@ int umr_get_wave_status_via_mmio(struct umr_asic *asic, unsigned se, unsigned sh
 		case 9: umr_read_wave_status_via_mmio_gfx8_9(asic, simd, wave, buf, &no_fields); break;
 		case 10:
 		case 11: umr_read_wave_status_via_mmio_gfx_10_11(asic, wave, buf, &no_fields); break;
+		case 12:
+			umr_read_wave_status_via_mmio_gfx_12(asic, wave, buf, &no_fields); break;
 	};
 	umr_grbm_select_index(asic, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL);
 
@@ -360,6 +393,8 @@ int umr_parse_wave_data_gfx(struct umr_asic *asic, struct umr_wave_status *ws, c
 		case 9: if (buf[0] != 1) { asic->err_msg("[ERROR]: Incorrect wave_data for GFX9\n"); return -1; }; break;
 		case 10: if (buf[0] != 2) { asic->err_msg("[ERROR]: Incorrect wave_data for GFX10\n"); return -1; }; break;
 		case 11: if (buf[0] != 3) { asic->err_msg("[ERROR]: Incorrect wave_data for GFX11\n"); return -1; }; break;
+		case 12:
+		if (buf[0] != 4) { asic->err_msg("[ERROR]: Incorrect wave_data for GFX12\n"); return -1; }; break;
 	};
 	for (x = 1; x < nwords; x++) {
 		ws->reg_values[x - 1] = buf[x];
@@ -542,6 +577,34 @@ static const char *gfx11_regs[] = {
 	NULL
 };
 
+static const char *gfx12_regs[] = {
+	"ixSQ_WAVE_STATUS",
+	"ixSQ_WAVE_PC_LO",
+	"ixSQ_WAVE_PC_HI",
+	"ixSQ_WAVE_EXEC_LO",
+	"ixSQ_WAVE_EXEC_HI",
+	"ixSQ_WAVE_HW_ID1",
+	"ixSQ_WAVE_HW_ID2",
+	"ixSQ_WAVE_GPR_ALLOC",
+	"ixSQ_WAVE_LDS_ALLOC",
+	"ixSQ_WAVE_TRAPSTS",
+	"ixSQ_WAVE_IB_STS",
+	"ixSQ_WAVE_IB_STS2",
+	"ixSQ_WAVE_IB_DBG1",
+	"ixSQ_WAVE_M0",
+	"ixSQ_WAVE_MODE",
+	"ixSQ_WAVE_STATE_PRIV",
+	"ixSQ_WAVE_EXCP_FLAG_PRIV",
+	"ixSQ_WAVE_EXCP_FLAG_USER",
+	"ixSQ_WAVE_TRAP_CTRL",
+	"ixSQ_WAVE_ACTIVE",
+	"ixSQ_WAVE_VALID_AND_IDLE",
+	"ixSQ_WAVE_DVGPR_ALLOC_LO",
+	"ixSQ_WAVE_DVGPR_ALLOC_HI",
+	"ixSQ_WAVE_SCHED_MODE",
+	NULL
+};
+
 int umr_wave_data_init(struct umr_asic *asic, struct umr_wave_data *wd) {
 	int maj, min;
 
@@ -560,6 +623,9 @@ int umr_wave_data_init(struct umr_asic *asic, struct umr_wave_data *wd) {
 		case 11:
 			wd->reg_names = gfx11_regs;
 			break;
+		case 12:
+			wd->reg_names = gfx12_regs;
+			break;
 		default:
 			return -1;
 	}
@@ -693,6 +759,7 @@ int umr_wave_data_get_flag_valid(struct umr_asic *asic, struct umr_wave_data *wd
 		case 9:
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "VALID");
 	}
 	return -1;
@@ -709,6 +776,7 @@ int umr_wave_data_get_flag_trap_en(struct umr_asic *asic, struct umr_wave_data *
 		case 9:
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "TRAP_EN");
 	}
 	return -1;
@@ -726,6 +794,8 @@ int umr_wave_data_get_flag_halt(struct umr_asic *asic, struct umr_wave_data *wd)
 		case 10:
 		case 11:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "HALT");
+		case 12:
+			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATE_PRIV", "HALT");
 	}
 	return -1;
 }
@@ -741,6 +811,7 @@ int umr_wave_data_get_flag_fatal_halt(struct umr_asic *asic, struct umr_wave_dat
 		case 9:
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "FATAL_HALT");
 	}
 	return -1;
@@ -757,6 +828,7 @@ int umr_wave_data_get_flag_priv(struct umr_asic *asic, struct umr_wave_data *wd)
 		case 9:
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "PRIV");
 	}
 	return -1;
@@ -774,6 +846,8 @@ int umr_wave_data_get_flag_wave64(struct umr_asic *asic, struct umr_wave_data *w
 		case 10:
 		case 11:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_IB_STS2", "WAVE64");
+		case 12:
+			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_STATUS", "WAVE64");
 	}
 	return -1;
 }
@@ -792,6 +866,7 @@ int umr_wave_data_get_shader_pc_vmid(struct umr_asic *asic, struct umr_wave_data
 			return 0;
 		case 10:
 		case 11:
+		case 12:
 			*addr = umr_wave_data_get_value(asic, wd, "ixSQ_WAVE_PC_LO") | ((uint64_t)umr_wave_data_get_value(asic, wd, "ixSQ_WAVE_PC_HI") << 32ULL);
 			*vmid = umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID2", "VM_ID");
 			return 0;
@@ -811,6 +886,7 @@ int umr_wave_data_get_flag_simd_id(struct umr_asic *asic, struct umr_wave_data *
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID", "SIMD_ID");
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID1", "SIMD_ID");
 	}
 	return -1;
@@ -828,6 +904,7 @@ int umr_wave_data_get_flag_wave_id(struct umr_asic *asic, struct umr_wave_data *
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID", "WAVE_ID");
 		case 10:
 		case 11:
+		case 12:
 			return umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID1", "WAVE_ID");
 	}
 	return -1;
@@ -843,7 +920,9 @@ uint32_t umr_wave_data_num_of_sgprs(struct umr_asic *asic, struct umr_wave_data
 		case 8:
 		case 9: return (umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_GPR_ALLOC", "SGPR_SIZE")) << 4;
 		case 10:
-		case 11: return 124;
+		case 11:
+		case 12: // TODO: confirm
+			return 124;
 	}
 	return 0;
 }
@@ -866,6 +945,7 @@ char *umr_wave_data_describe_wavefront(struct umr_asic *asic, struct umr_wave_da
 			break;
 		case 10:
 		case 11:
+		case 12:
 			snprintf(str, sizeof(str)-1, "se%" PRIu32 ".sa%" PRIu32 ".wgp%" PRIu32 ".simd%" PRIu32 ".wave%" PRIu32,
 				wd->se, wd->sh, wd->cu,
 				umr_wave_data_get_bits(asic, wd, "ixSQ_WAVE_HW_ID1", "SIMD_ID"),
diff --git a/src/lib/sdma_decode_opcodes.c b/src/lib/sdma_decode_opcodes.c
index 278de55a85459527aff7721f48c31e31e290a9c7..cfc1105a3a702be9b281334dbe92eb02249b0183 100644
--- a/src/lib/sdma_decode_opcodes.c
+++ b/src/lib/sdma_decode_opcodes.c
@@ -1433,7 +1433,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 			switch (stream->sub_opcode) {
 				case 0: // POLL_REGMEM
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REGMEM", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 20) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 20) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 24) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "HDP_FLUSH", (stream->header_dw >> 26) & 1, NULL, 16, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "FUNCTION", 0, poll_regmem_funcs[(stream->header_dw >> 28) & 7], 0, 32);
@@ -1456,7 +1456,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 					return;
 				case 1: // POLL_REG_WRITE_MEM
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REG_WRITE_MEM", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR", fetch_word(asic, stream, 0), NULL, 16, 32);
 					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 1), NULL, 16, 32);
@@ -1465,7 +1465,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 				case 2: // POLL_DBIT_WRITE_MEM
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_DBIT_WRITE_MEM", stream->header_dw, stream->words);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "EA", (stream->header_dw >> 16) & 0x3, NULL, 10, 32);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 0), NULL, 16, 32);
 					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_HI", fetch_word(asic, stream, 1), NULL, 16, 32);
@@ -1474,7 +1474,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 					return;
 				case 3: // MEM_VERIFY
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "MEM_VERIFY", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "MODE", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "PATTERN", fetch_word(asic, stream, 0), NULL, 16, 32);
@@ -1508,7 +1508,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 			break;
 		case 9:  // COND_EXE
 			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COND_EXE", stream->header_dw, stream->words);
-			if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+			if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 			if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 			ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", fetch_word(asic, stream, 0), NULL, 16, 32);
 			ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDR_HI", fetch_word(asic, stream, 1), NULL, 16, 32);
@@ -1519,7 +1519,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "ATOMIC", stream->header_dw, stream->words);
 			ui->add_field(ui, ib_addr + 0, ib_vmid, "LOOP", (stream->header_dw >> 16) & 1, NULL, 16, 32);
 			ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
-			if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 20) & 0x7, NULL, 10, 32);
+			if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 20) & 0x7, NULL, 16, 32);
 			if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 24) & 0x1, NULL, 10, 32);
 			ui->add_field(ui, ib_addr + 0, ib_vmid, "OP", (stream->header_dw >> 25) & 0x7F, NULL, 16, 32);
 			ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", fetch_word(asic, stream, 0), NULL, 16, 32);
@@ -1535,7 +1535,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 				case 0: // CONST_FILL
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "CONST_FILL", stream->header_dw, stream->words);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "SWAP", (stream->header_dw >> 16) & 0x3, NULL, 10, 32);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "FILL_SIZE", (stream->header_dw >> 30) & 0x3, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "CONST_FILL_DST_LO", fetch_word(asic, stream, 0), NULL, 16, 32);
@@ -1545,7 +1545,7 @@ static void decode_upto_ai(struct umr_asic *asic, struct umr_stream_decode_ui *u
 					return;
 				case 1: // CONST_FILL (DATA_FILL_MULTI)
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "CONST_FILL (DATA_FILL_MULTI)", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 24) & 0x7, NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", (stream->header_dw >> 28) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "MEMLOG_CLR", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "BYTE_STRIDE", fetch_word(asic, stream, 0), NULL, 10, 32);
@@ -1979,6 +1979,7 @@ static void decode_upto_nv(struct umr_asic *asic, struct umr_stream_decode_ui *u
 						ui->add_field(ui, ib_addr + 24 + 4 * (n - 2), ib_vmid, str_buf, fetch_word(asic, stream, n + 3), NULL, 16, 32);
 					}
 					return;
+
 				case 16: // LINEAR_BC
 					break; // fall through
 				case 17: // TILED_BC
@@ -2078,7 +2079,7 @@ static void decode_upto_nv(struct umr_asic *asic, struct umr_stream_decode_ui *u
 			switch (stream->sub_opcode) {
 				case 0: // POLL_REGMEM
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REGMEM", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 20, 23), NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 20, 23), NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", BITS(stream->header_dw, 24, 25), NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "HDP_FLUSH", BITS(stream->header_dw, 26, 27), NULL, 16, 32);
 					ui->add_field(ui, ib_addr + 0, ib_vmid, "FUNCTION", 0, poll_regmem_funcs[BITS(stream->header_dw, 28, 31)], 0, 32);
@@ -2101,7 +2102,7 @@ static void decode_upto_nv(struct umr_asic *asic, struct umr_stream_decode_ui *u
 					return;
 				case 1: // POLL_REG_WRITE_MEM
 					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REG_WRITE_MEM", stream->header_dw, stream->words);
-					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 24, 27), NULL, 10, 32);
+					if (sc->has_cp_fields) ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 24, 27), NULL, 16, 32);
 					if (sc->has_cpv_flag) ui->add_field(ui, ib_addr + 0, ib_vmid, "CPV", BITS(stream->header_dw, 28, 29), NULL, 10, 32);
 					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR", BITS(fetch_word(asic, stream, 0), 2, 32) << 2, umr_reg_name(asic, BITS(fetch_word(asic, stream, 0), 2, 32)), 16, 32);
 					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_LO", fetch_word(asic, stream, 1), NULL, 16, 32);
@@ -2201,6 +2202,695 @@ static void decode_upto_nv(struct umr_asic *asic, struct umr_stream_decode_ui *u
 	decode_upto_ai(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, sc);
 }
 
+static void decode_upto_oss7(struct umr_asic *asic, struct umr_stream_decode_ui *ui, struct umr_sdma_stream *stream,
+			   uint64_t ib_addr, uint32_t ib_vmid, uint64_t from_addr, uint64_t from_vmid, int follow, struct sdma_config *sc)
+{
+	uint32_t n, x;
+	char str_buf[128];
+	(void)from_addr;
+	(void)from_vmid;
+	switch (stream->opcode) {
+		case 1: // COPY
+			switch (stream->sub_opcode) {
+				case 0: // LINEAR
+					switch (stream->header_dw & (1UL << 27)) {
+						case 0: // not broadcast
+							ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (LINEAR)", stream->header_dw, stream->words);
+							ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 0, ib_vmid, "DCC", (stream->header_dw >> 19) & 0x1, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 0, ib_vmid, "BROADCAST", (stream->header_dw >> 27) & 0x1, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 4, ib_vmid, "COPY_COUNT", stream->words[0], NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "DST2_CACHE_POLICY", (stream->words[1] >> 12) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_CACHE_POLICY", (stream->words[1] >> 20) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_CACHE_POLICY", (stream->words[1] >> 28) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_ADDR_LO", stream->words[2], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_ADDR_HI", stream->words[3], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 20, ib_vmid, "DST_ADDR_LO", stream->words[4], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 24, ib_vmid, "DST_ADDR_HI", stream->words[5], NULL, 16, 32);
+							if ((stream->header_dw >> 19) & 0x1) { // DCC = 1
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "DATA_FORMAT", BITS(stream->words[6], 0, 6), NULL, 10, 32);
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "NUM_TYPE", BITS(stream->words[6], 9, 12), NULL, 10, 32);
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "RD_CM", BITS(stream->words[6], 16, 18), NULL, 10, 32);
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "WR_CM", BITS(stream->words[6], 18, 20), NULL, 10, 32);
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "MAX_COM", BITS(stream->words[6], 24, 26), NULL, 10, 32);
+								ui->add_field(ui, ib_addr + 28, ib_vmid, "MAX_UC", BITS(stream->words[6], 26, 27), NULL, 10, 32);
+							}
+							return;
+						case 1: // broadcast
+							ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (LINEAR BROADCAST)", stream->header_dw, stream->words);
+							ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 0, ib_vmid, "BROADCAST", (stream->header_dw >> 27) & 0x1, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 4, ib_vmid, "COPY_COUNT", stream->words[0], NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "DST2_SW", (stream->words[1] >> 8) & 3, NULL, 10, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "DST2_CACHE_POLICY", (stream->words[1] >> 12) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_CACHE_POLICY", (stream->words[1] >> 20) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_CACHE_POLICY", (stream->words[1] >> 28) & 0x7, NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_ADDR_LO", stream->words[2], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_ADDR_HI", stream->words[3], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 20, ib_vmid, "DST_ADDR_LO", stream->words[4], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 24, ib_vmid, "DST_ADDR_HI", stream->words[5], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 28, ib_vmid, "DST2_ADDR_LO", stream->words[6], NULL, 16, 32);
+							ui->add_field(ui, ib_addr + 32, ib_vmid, "DST2_ADDR_HI", stream->words[7], NULL, 16, 32);
+							return;
+						default:
+							break;
+					}
+					break;
+				case 1: // TILED
+					if ((stream->header_dw >> 26) & 0x3) { // L2T BROADCAST or L2T FRAME TO FIELD
+						if ((stream->header_dw >> 26) & 0x1) {
+							ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (L2T_FRAME_TO_FIELD)", stream->header_dw, stream->words);
+						} else {
+							ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (L2T_BROADCAST)", stream->header_dw, stream->words);
+						}
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "MIP MAX", BITS(stream->header_dw, 20, 25), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "VIDEOCOPY", (stream->header_dw >> 26) & 0x1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "BROADCAST", (stream->header_dw >> 27) & 0x1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 4, ib_vmid, "TILED_ADDR0_LO", stream->words[0], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 8, ib_vmid, "TILED_ADDR0_HI", stream->words[1], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 12, ib_vmid, "TILED_ADDR1_LO", stream->words[2], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 16, ib_vmid, "TILED_ADDR1_HI", stream->words[3], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 20, ib_vmid, "WIDTH", BITS(stream->words[4], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 24, ib_vmid, "HEIGHT", BITS(stream->words[5], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 24, ib_vmid, "DEPTH", BITS(stream->words[5], 16, 30), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "ELEMENT_SIZE", stream->words[6] & 0x7, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "SWIZZLE_MODE", BITS(stream->words[6], 3, 8), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "DIMENSION", BITS(stream->words[6], 9, 11), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 32, ib_vmid, "X", BITS(stream->words[7], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 32, ib_vmid, "Y", BITS(stream->words[7], 16, 32), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 36, ib_vmid, "Z", BITS(stream->words[8], 0, 14), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 40, ib_vmid, "T1 CACHE POLICY", (stream->words[9] >> 12) & 0x7, NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 40, ib_vmid, "LINEAR_CACHE_POLICY", (stream->words[9] >> 20) & 0x7, NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 40, ib_vmid, "T0 CACHE POLICY", (stream->words[9] >> 28) & 0x7, NULL, 16, 32);
+
+						ui->add_field(ui, ib_addr + 44, ib_vmid, "LINEAR_ADDR_LO", stream->words[10], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 48, ib_vmid, "LINEAR_ADDR_HI", stream->words[11], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 52, ib_vmid, "LINEAR_PITCH", BITS(stream->words[12], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "LINEAR_SLICE_PITCH", stream->words[13], NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "COUNT", BITS(stream->words[14], 0, 30), NULL, 10, 32);
+						return;
+					} else {
+						ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (TILED)", stream->header_dw, stream->words);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "MIP MAX", BITS(stream->header_dw, 20, 25), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 0, ib_vmid, "DETILE", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 4, ib_vmid, "TILED_ADDR_LO", stream->words[0], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 8, ib_vmid, "TILED_ADDR_HI", stream->words[1], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 12, ib_vmid, "WIDTH", BITS(stream->words[2], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 16, ib_vmid, "HEIGHT", BITS(stream->words[3], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 16, ib_vmid, "DEPTH", BITS(stream->words[3], 16, 30), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 20, ib_vmid, "ELEMENT_SIZE", BITS(stream->words[4], 0, 3), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 20, ib_vmid, "SWIZZLE_MODE", BITS(stream->words[4], 3, 8), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 20, ib_vmid, "DIMENSION", BITS(stream->words[4], 9, 11), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 24, ib_vmid, "X", BITS(stream->words[5], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 24, ib_vmid, "Y", BITS(stream->words[5], 16, 32), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "Z", BITS(stream->words[6], 0, 14), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "LINEAR CACHE POLICY", BITS(stream->words[6], 20, 23), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 28, ib_vmid, "TILED CACHE POLICY", BITS(stream->words[6], 28, 31), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 32, ib_vmid, "LINEAR_ADDR_LO", stream->words[7], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 36, ib_vmid, "LINEAR_ADDR_HI", stream->words[8], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 40, ib_vmid, "LINEAR_PITCH", BITS(stream->words[9], 0, 16), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 44, ib_vmid, "LINEAR_SLICE_PITCH", stream->words[10], NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 48, ib_vmid, "COUNT", BITS(stream->words[11], 0, 30), NULL, 10, 32);
+						return;
+					}
+				case 3: // SOA
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (STRUCT)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "DETILE", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SB_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SB_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "START_INDEX", stream->words[2], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "COUNT", stream->words[3], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "STRIDE", BITS(stream->words[4], 0, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "STRUCT CACHE POLICY", BITS(stream->words[4], 28, 31), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "LINEAR CACHE POLICY", BITS(stream->words[4], 20, 23), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "LINEAR_ADDR_LO", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "LINEAR_ADDR_HI", stream->words[6], NULL, 16, 32);
+					return;
+				case 4: // LINEAR_SUB_WINDOW
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (LINEAR_SUB_WINDOW)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "ELEMENTSIZE", BITS(stream->header_dw, 29, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_X", BITS(stream->words[2], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_Y", BITS(stream->words[2], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_Z", BITS(stream->words[3], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_PITCH", BITS(stream->words[3], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "SRC_SLICE_PITCH", stream->words[4], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "DST_ADDR_LO", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "DST_ADDR_HI", stream->words[6], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "DST_X", BITS(stream->words[7], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "DST_Y", BITS(stream->words[7], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "DST_Z", BITS(stream->words[8], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "DST_PITCH", BITS(stream->words[8], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "DST_SLICE_PITCH", stream->words[9], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "RECT_X", BITS(stream->words[10], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "RECT_Y", BITS(stream->words[10], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "RECT_Z", BITS(stream->words[11], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_CACHE_POLICY", (stream->words[11] >> 20) & 0x7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "SRC_CACHE_POLICY", (stream->words[11] >> 28) & 0x7, NULL, 16, 32);
+					return;
+				case 5: // TILED_SUB_WINDOW
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (TILED_SUB_WINDOW)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "DCC", (stream->header_dw >> 19) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "DETILE", stream->header_dw >> 31, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "TILED_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "TILED_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "TILED_X", BITS(stream->words[2], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "TILED_Y", BITS(stream->words[2], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "TILED_Z", BITS(stream->words[3], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "WIDTH", BITS(stream->words[3], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "HEIGHT", BITS(stream->words[4], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "DEPTH", BITS(stream->words[4], 16, 30), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "ELEMENT_SIZE", BITS(stream->words[5], 0, 3), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SWIZZLE_MODE", BITS(stream->words[5], 3, 8), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "DIMENSION", BITS(stream->words[5], 9, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "MIP_MAX", BITS(stream->words[5], 16, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "MIP_ID", BITS(stream->words[5], 24, 29), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "LINEAR_ADDR_LO", stream->words[6], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "LINEAR_ADDR_HI", stream->words[7], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "LINEAR_X", BITS(stream->words[8], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "LINEAR_Y", BITS(stream->words[8], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "LINEAR_Z", BITS(stream->words[9], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "LINEAR_PITCH", BITS(stream->words[9], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "LINEAR_SLICE_PITCH", stream->words[10], NULL, 10, 32);
+
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "RECT_X", BITS(stream->words[11], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "RECT_Y", BITS(stream->words[11], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "RECT_Z", BITS(stream->words[12], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "LINEAR_CACHE_POLICY", (stream->words[12] >> 20) & 0x7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "TILE_CACHE_POLICY", (stream->words[12] >> 28) & 0x7, NULL, 16, 32);
+
+					if ((stream->header_dw >> 19) & 0x1) { // DCC = 1
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "DATA FORMAT", BITS(stream->words[13], 0, 6), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "NUM TYPE", BITS(stream->words[13], 9, 12), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "READ CM", BITS(stream->words[13], 16, 18), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "WRITE CM", BITS(stream->words[13], 18, 20), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "MAX COM", BITS(stream->words[13], 24, 26), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 56, ib_vmid, "MAX UCOM", BITS(stream->words[13], 26, 27), NULL, 10, 32);
+					}
+					return;
+				case 6: // T2T_SUB_WINDOW
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (T2T_SUB_WINDOW)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "DCC", (stream->header_dw >> 19) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_X", BITS(stream->words[2], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_Y", BITS(stream->words[2], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_Z", BITS(stream->words[3], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_WIDTH", BITS(stream->words[3], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "SRC_HEIGHT", BITS(stream->words[4], 0, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "SRC_DEPTH", BITS(stream->words[4], 16, 30), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_ELEMENT_SIZE", BITS(stream->words[5], 0, 3), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_SWIZZLE_MODE", BITS(stream->words[5], 3, 8), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_DIMENSION", BITS(stream->words[5], 9, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_MIP_MAX", BITS(stream->words[5], 16, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_MIP_ID", BITS(stream->words[5], 24, 29), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "DST_ADDR_LO", stream->words[6], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "DST_ADDR_HI", stream->words[7], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "DST_X", BITS(stream->words[8], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "DST_Y", BITS(stream->words[8], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "DST_Z", BITS(stream->words[9], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "DST_WIDTH", BITS(stream->words[9], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "DST_HEIGHT", BITS(stream->words[10], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "DST_DEPTH", BITS(stream->words[10], 16, 30), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_ELEMENT_SIZE", BITS(stream->words[11], 0, 3), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_SWIZZLE_MODE", BITS(stream->words[11], 3, 8), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_DIMENSION", BITS(stream->words[11], 9, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_MIP_MAX", BITS(stream->words[11], 16, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_MIP_ID", BITS(stream->words[11], 24, 29), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "RECT_X", BITS(stream->words[12], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "RECT_Y", BITS(stream->words[12], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 56, ib_vmid, "RECT_Z", BITS(stream->words[13], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 56, ib_vmid, "DST_CACHE_POLICY", (stream->words[13] >> 20) & 0x7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 56, ib_vmid, "SRC_CACHE_POLICY", (stream->words[13] >> 28) & 0x7, NULL, 16, 32);
+
+					if ((stream->header_dw >> 19) & 0x1) { // DCC = 1
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "DATA FORMAT", BITS(stream->words[14], 0, 6), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "NUM TYPE", BITS(stream->words[14], 9, 12), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "READ CM", BITS(stream->words[14], 16, 18), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "WRITE CM", BITS(stream->words[14], 18, 20), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "MAX COM", BITS(stream->words[14], 24, 26), NULL, 10, 32);
+						ui->add_field(ui, ib_addr + 60, ib_vmid, "MAX UCOM", BITS(stream->words[14], 26, 27), NULL, 10, 32);
+					}
+					return;
+				case 8: // LINEAR_PHY
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (LINEAR_PHY)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "COUNT", BITS(stream->words[0], 0, 22), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_PAIR", BITS(stream->words[0], 24, 32), NULL, 10, 32);
+
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_CACHE_POLICY", BITS(stream->words[1], 8, 11), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_CACHE_POLICY", BITS(stream->words[1], 16, 19), NULL, 16, 32);
+
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_GCC", (stream->words[1] >> 19) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_SYS", (stream->words[1] >> 20) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_LOG", (stream->words[1] >> 21) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_SNOOP", (stream->words[1] >> 22) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_GPA", (stream->words[1] >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_GCC", (stream->words[1] >> 27) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_SYS", (stream->words[1] >> 28) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_SNOOP", (stream->words[1] >> 30) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_GPA", (stream->words[1] >> 31) & 0x1, NULL, 10, 32);
+
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DATA_FORMAT", BITS(stream->words[2], 0, 6), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "NUM_TYPE", BITS(stream->words[2], 9, 12), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "RD_CM", BITS(stream->words[2], 16, 18), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "WR_CM", BITS(stream->words[2], 18, 20), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "MAX_COM", BITS(stream->words[2], 24, 26), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "MAX_UC", BITS(stream->words[2], 26, 27), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DCC", BITS(stream->words[2], 31, 32), NULL, 10, 32);
+
+					for (n = 3; n + 3 < stream->nwords; n += 4) {
+						uint32_t addr_idx = (n - 3) / 4;
+						sprintf(str_buf, "SRC_ADDR%"PRIu32"_LO", addr_idx);
+						ui->add_field(ui, ib_addr + 16 + 4 * (n - 3), ib_vmid, str_buf, stream->words[n], NULL, 16, 32);
+						sprintf(str_buf, "SRC_ADDR%"PRIu32"_HI", addr_idx);
+						ui->add_field(ui, ib_addr + 20 + 4 * (n - 3), ib_vmid, str_buf, stream->words[n + 1], NULL, 16, 32);
+						sprintf(str_buf, "DST_ADDR%"PRIu32"_LO", addr_idx);
+						ui->add_field(ui, ib_addr + 24 + 4 * (n - 3), ib_vmid, str_buf, stream->words[n + 2], NULL, 16, 32);
+						sprintf(str_buf, "DST_ADDR%"PRIu32"_HI", addr_idx);
+						ui->add_field(ui, ib_addr + 28 + 4 * (n - 3), ib_vmid, str_buf, stream->words[n + 3], NULL, 16, 32);
+					}
+					return;
+				case 12: // PAGE TRANSFER COPY
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "PAGE TRANSFER COPY", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "D", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "PAGE_SIZE", BITS(stream->header_dw, 24, 28), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "PTE CACHE POLICY", BITS(stream->words[0], 0, 3), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SYS", BITS(stream->words[0], 4, 5), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "PTE_SNP", BITS(stream->words[0], 6, 7), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "LOCAL CACHE POLICY", BITS(stream->words[0], 8, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "LOCAL_SNP", BITS(stream->words[0], 14, 15), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SYSMEM CACHE POLICY", BITS(stream->words[0], 16, 19), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SYSMEM_SNP", BITS(stream->words[0], 22, 23), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SYSMEM_ADDR_ARRAY_NUM", n = BITS(stream->words[0], 24, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DATA_FORMAT", BITS(stream->words[1], 0, 6), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "NUM_TYPE", BITS(stream->words[1], 9, 12), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "RD_CM", BITS(stream->words[1], 16, 18), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "WR_CM", BITS(stream->words[1], 18, 20), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "MAX_COM", BITS(stream->words[1], 24, 26), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "MAX_UC", BITS(stream->words[1], 26, 27), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DCC", BITS(stream->words[1], 31, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "PTE_MASK_LOW", BITS(stream->words[2], 0, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "PTE_MASK_HI", BITS(stream->words[3], 0, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "PTE_ADDR_LOW", BITS(stream->words[4], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "PTE_ADDR_HI", BITS(stream->words[5], 0, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "LOCALMEM_ADDR_LOW", BITS(stream->words[6], 0, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "LOCALMEM_ADDR_HI", BITS(stream->words[7], 0, 32), NULL, 16, 32);
+					++n;
+					for (x = 0; x < n && (8 + x + x) < stream->nwords; x++) {
+						ui->add_field(ui, ib_addr + 36 + (x + x + 0) * 4, ib_vmid, "SYSMEM_ADDR_LOW", stream->words[8 + x + x + 0], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 36 + (x + x + 1) * 4, ib_vmid, "SYSMEM_ADDR_HIGH", stream->words[8 + x  + x + 1], NULL, 16, 32);
+					}
+					return;
+				case 36: // SUBWIN_LARGE
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COPY (SUBWIN_LARGE)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_X", stream->words[2], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_Y", stream->words[3], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "SRC_Z", stream->words[4], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "SRC_PITCH", stream->words[5], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "SRC_SLICE_PITCH_LO", stream->words[6], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "SRC_SLICE_PITCH_47_32", stream->words[7] & 0xFFFF, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "DST_ADDR_LO", stream->words[8], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 40, ib_vmid, "DST_ADDR_HI", stream->words[9], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 44, ib_vmid, "DST_X", stream->words[10], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 48, ib_vmid, "DST_Y", stream->words[11], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 52, ib_vmid, "DST_Z", stream->words[12], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 56, ib_vmid, "DST_PITCH", stream->words[13], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 60, ib_vmid, "DST_SLICE_PITCH_LO", stream->words[14], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 64, ib_vmid, "DST_SLICE_PITCH_47_32", stream->words[15] & 0xFFFF, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 64, ib_vmid, "DST_POLICY", (stream->words[15] >> 20) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 64, ib_vmid, "SRC_POLICY", (stream->words[15] >> 28) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 68, ib_vmid, "RECT_X", stream->words[16], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 72, ib_vmid, "RECT_Y", stream->words[17], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 76, ib_vmid, "RECT_Z", stream->words[18], NULL, 10, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 2: // WRITE
+			switch (stream->sub_opcode) {
+				case 0: // LINEAR
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "WRITE (LINEAR)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", BITS(stream->header_dw, 18, 19), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "NOPTE_COMP", BITS(stream->header_dw, 16, 17), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "COUNT", BITS(stream->words[2], 0, 20), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "CACHE_POLICY", BITS(stream->words[2], 28, 31), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SYS", BITS(stream->words[2], 20, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "SNP", BITS(stream->words[2], 22, 23), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "GPA", BITS(stream->words[2], 23, 24), NULL, 10, 32);
+					for (n = 3; n < stream->nwords; n++) {
+						uint32_t data_idx = n - 3;
+						sprintf(str_buf, "DATA_%"PRIu32, data_idx);
+						ui->add_field(ui, ib_addr + 16 + 4 * (n - 3), ib_vmid, str_buf, stream->words[n], NULL, 16, 32);
+					}
+					return;
+				case 1: // TILED
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "WRITE (TILED)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "MIP MAX", BITS(stream->header_dw, 20, 25), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "WIDTH", BITS(stream->words[2], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "HEIGHT", BITS(stream->words[3], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "DEPTH", BITS(stream->words[3], 16, 30), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "ELEMENT_SIZE", BITS(stream->words[4], 0, 3), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "SWIZZLE_MODE", BITS(stream->words[4], 3, 8), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "DIMENSION", BITS(stream->words[4], 9, 11), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "X", BITS(stream->words[5], 0, 16), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "Y", BITS(stream->words[5], 16, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "Z", BITS(stream->words[6], 0, 14), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "CACHE_POLICY", BITS(stream->words[6], 28, 31), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "COUNT", BITS(stream->words[7], 0, 20), NULL, 10, 32);
+					for (n = 8; n < stream->nwords; n++) {
+						uint32_t data_idx = n - 8;
+						sprintf(str_buf, "DATA_%"PRIu32, data_idx);
+						ui->add_field(ui, ib_addr + 36 + 4 * (n - 8), ib_vmid, str_buf, stream->words[n], NULL, 16, 32);
+					}
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 4: // INDIRECT
+			break; // fall through
+		case 5: // FENCE
+			switch (stream->sub_opcode) {
+				case 0: // FENCE
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "FENCE", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SYS", (stream->header_dw >> 20) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SNP", (stream->header_dw >> 22) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GPA", (stream->header_dw >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "FENCE_ADDR_LO", BITS(stream->words[0], 2, 32) << 2, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "FENCE_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "FENCE_DATA", stream->words[2], NULL, 16, 32);
+					return;
+				case 1: // FENCE CONDITIONAL INTERRUPT
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "FENCE", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SYS", (stream->header_dw >> 20) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SNP", (stream->header_dw >> 22) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GPA", (stream->header_dw >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "QW", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "FENCE_ADDR_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "FENCE_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "FENCE_DATA_LO", stream->words[2], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "FENCE_DATA_HI", stream->words[3], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "FENCE_REF_ADDR_LO", stream->words[4], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "FENCE_REF_ADDR_HI", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "INTERRUPT_CONTEXT", stream->words[6], NULL, 16, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 6: // TRAP
+			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "TRAP", stream->header_dw, stream->words);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "TRAP_INT_CONTEXT", stream->words[0], NULL, 16, 32);
+			return;
+		case 7: // SEM
+			switch (stream->sub_opcode) {
+				case 1: // MEM_INCR
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "SEM (MEM_INCR)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", BITS(stream->words[0], 3, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDR_HI", stream->words[1], NULL, 16, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+
+			break;
+		case 8: // POLL_REGMEM
+			switch (stream->sub_opcode) {
+				case 0: // POLL_REGMEM (DONE)
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REGMEM", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 22, 25), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "MODE", BITS(stream->header_dw, 26, 28), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "FUNC", BITS(stream->header_dw, 28, 31), poll_regmem_funcs[BITS(stream->header_dw, 28, 31)], 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "M", BITS(stream->header_dw, 31, 32), NULL, 16, 32);
+					if (!(stream->header_dw & (1UL << 31))) {
+						ui->add_field(ui, ib_addr + 4, ib_vmid, "REGISTER", BITS(stream->words[0], 2, 32) << 2, umr_reg_name(asic, BITS(stream->words[0], 2, 32)), 16, 32);
+						if (((stream->header_dw >> 26) & 3) == 1) { // if HDP_FLUSH, the write register is provided
+							ui->add_field(ui, ib_addr + 8, ib_vmid, "REGISTER", BITS(stream->words[1], 2, 32) << 2, umr_reg_name(asic, BITS(stream->words[1], 2, 32)), 16, 32);
+						} else {
+							ui->add_field(ui, ib_addr + 8, ib_vmid, NULL, stream->words[1], NULL, 16, 32);
+						}
+					} else {
+						ui->add_field(ui, ib_addr + 4, ib_vmid, "POLL_REGMEM_ADDR_LO", stream->words[0], NULL, 16, 32);
+						ui->add_field(ui, ib_addr + 8, ib_vmid, "POLL_REGMEM_ADDR_HI", stream->words[1], NULL, 16, 32);
+					}
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "VALUE", stream->words[2], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "MASK", stream->words[3], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "INTERVAL", stream->words[4] & 0xFFFF, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "RETRY_COUNT", (stream->words[4] >> 16) & 0xFFF, NULL, 10, 32);
+					return;
+				case 1: // POLL_REG_WRITE_MEM (DONE)
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_REG_WRITE_MEM", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 22) & 0x7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_REG_ADDR", BITS(stream->words[0], 2, 20) << 2, umr_reg_name(asic, BITS(stream->words[0], 2, 20)), 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_LO", BITS(stream->words[1], 2, 32) << 2, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DST_ADDR_HI", stream->words[2], NULL, 16, 32);
+					return;
+				case 2: // POLL_DBIT_WRITE_MEM (DONE)
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "POLL_DBIT_WRITE_MEM", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 16) & 0x7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "DP", (stream->header_dw >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "VFID", BITS(stream->header_dw, 24, 29), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_ADDR_LO", BITS(stream->words[0], 5, 32) << 5, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "START_PAGE", BITS(stream->words[2], 0, 31), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "PAGE_NUM", stream->words[3], NULL, 16, 32);
+					return;
+				case 4: // INVALIDATION
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "INVALIDATION", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GFX_ENG_ID", BITS(stream->header_dw, 16, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "MM_ENG_ID", BITS(stream->header_dw, 24, 29), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "INVALIDATE_REQ", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDRESSRANGE_LO", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "INVALIDATE_ACK", BITS(stream->words[2], 0, 16), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "ADDRESSRANGE_HI", BITS(stream->words[2], 16, 30), NULL, 16, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 9:  // COND_EXE
+			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "COND_EXE", stream->header_dw, stream->words);
+			ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 26) & 0x7, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", BITS(stream->words[0], 2, 32) << 2, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDR_HI", stream->words[1], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "REFERENCE", stream->words[2], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "EXEC_COUNT", BITS(stream->words[3], 0, 14), NULL, 10, 32);
+			return;
+		case 10:  // ATOMIC
+			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "ATOMIC", stream->header_dw, stream->words);
+			ui->add_field(ui, ib_addr + 0, ib_vmid, "LOOP", (stream->header_dw >> 16) & 1, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 0, ib_vmid, "TMZ", (stream->header_dw >> 18) & 0x1, NULL, 10, 32);
+			ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 22) & 0x7, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 0, ib_vmid, "ATOMIC_OP", (stream->header_dw >> 25) & 0x7F, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", BITS(stream->words[0], 2, 32) << 2, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDR_HI", stream->words[1], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "SRC_DATA_LO", stream->words[2], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 16, ib_vmid, "SRC_DATA_HI", stream->words[3], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 20, ib_vmid, "CMP_DATA_LO", stream->words[4], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 24, ib_vmid, "CMP_DATA_HI", stream->words[5], NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 28, ib_vmid, "LOOP_INTERVAL", BITS(stream->words[6], 0, 13), NULL, 16, 32);
+			return;
+		case 11: // CONST_FILL
+			switch (stream->sub_opcode) {
+				case 0: // CONST_FILL
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "CONST_FILL", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "NOPTE_COMP", BITS(stream->header_dw, 16, 17), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SYS", BITS(stream->header_dw, 20, 21), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SNP", BITS(stream->header_dw, 22, 23), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GPA", BITS(stream->header_dw, 23, 24), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", BITS(stream->header_dw, 26, 29), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "FILL_SIZE", BITS(stream->header_dw, 30, 32), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "CONST_FILL_DST_LO", stream->words[0], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "CONST_FILL_DST_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "CONST_FILL_DATA", stream->words[2], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "CONST_FILL_BYTE_COUNT", BITS(stream->words[3], 0, 30), NULL, 10, 32);
+					return;
+				case 1: // CONST_FILL (DATA_FILL_MULTI)
+					break; // fall through 
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 12: // GEN_PTEPDE
+			switch (stream->sub_opcode) {
+				case 0: // GEN_PTEPDE
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GEN_PTEPDE", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SYS", (stream->header_dw >> 20) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SNP", (stream->header_dw >> 22) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GPA", (stream->header_dw >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "DST_ADDR_LO", BITS(stream->words[0], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "DST_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "MASK_LO", stream->words[2], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "MASK_HI", stream->words[3], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "INIT_LO", stream->words[4], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "INIT_HI", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "INCR_LO", stream->words[6], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 32, ib_vmid, "INCR_HI", stream->words[7], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 36, ib_vmid, "numPTE", BITS(stream->words[8], 0, 19), NULL, 10, 32);
+					return;
+				case 1: // COPY
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GEN_PTEPDE (COPY)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "PTEPDE_OP", (stream->header_dw >> 31) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "SRC_ADDR_LO", BITS(stream->words[0], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "SRC_ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DST_ADDR_LO", BITS(stream->words[2], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "DST_ADDR_HI", stream->words[3], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "MASK_LO", stream->words[4], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "MASK_HI", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "numPTE", BITS(stream->words[6], 0, 19), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "DST CACHE POLICY", BITS(stream->words[6], 24, 27), NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "SRC CACHE POLICY", BITS(stream->words[6], 28, 31), NULL, 10, 32);
+					return;
+				case 2: // RMW
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GEN_PTEPDE (RMW)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SYS", (stream->header_dw >> 20) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "SNP", (stream->header_dw >> 22) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "GPA", (stream->header_dw >> 23) & 0x1, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE_POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR_LO", BITS(stream->words[0], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "ADDR_HI", stream->words[1], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "MASK_LO", stream->words[2], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "MASK_HI", stream->words[3], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 20, ib_vmid, "VALUE_LO", stream->words[4], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 24, ib_vmid, "VALUE_HI", stream->words[5], NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 28, ib_vmid, "numPTE", BITS(stream->words[6], 0, 19), NULL, 10, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 13: // TIMESTAMP
+			switch (stream->sub_opcode) {
+				case 0: // TIMESTAMP_SET
+					break; // fall through
+				case 1: // TIMESTAMP_GET
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "TIMESTAMP (GET)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "WRITE_ADDR_LO", BITS(stream->words[0], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "WRITE_ADDR_HI", stream->words[1], NULL, 16, 32);
+					return;
+				case 2: // TIMESTAMP_GET_GLOBAL
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "TIMESTAMP (GET_GLOBAL)", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 0, ib_vmid, "CACHE POLICY", (stream->header_dw >> 26) & 0x7, NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "WRITE_ADDR_LO", BITS(stream->words[0], 3, 32) << 3, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "WRITE_ADDR_HI", stream->words[1], NULL, 16, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 14: // WRITE REG
+			switch (stream->sub_opcode) {
+				case 0: // REGISTER WRITE
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "SRBM_WRITE", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "REG_WRITE_ADDR", BITS(stream->words[0], 2, 32) << 2, umr_reg_name(asic, BITS(stream->words[0], 2, 32)), 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "REG_WRITE_DATA", stream->words[1], NULL, 16, 32);
+					if (BITS(stream->header_dw, 19, 20))
+						ui->add_field(ui, ib_addr + 12, ib_vmid, "GRBM_GFX_INDEX_DATA", stream->words[2], NULL, 16, 32);
+					return;
+				case 1: // RMW_REGISTER
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "RMW_REGISTER", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "ADDR", BITS(stream->words[0], 2, 32) << 2, umr_reg_name(asic, BITS(stream->words[0], 2, 32)), 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "MASK", stream->words[1], NULL, 10, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "DATA", stream->words[2], NULL, 10, 32);
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+		case 15: // Pred Exe (same as VI)
+			break; // fallthrough
+		case 16: // GPUVM_INV (NV and beyond)
+			ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GPUVM_INV", stream->header_dw, stream->words);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "PER_VMID_INV_REQ", BITS(stream->words[0], 0, 16), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "FLUSH_TYPE", BITS(stream->words[0], 16, 19), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2_PTES", BITS(stream->words[0], 19, 20), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2_PDE0", BITS(stream->words[0], 20, 21), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2_PDE1", BITS(stream->words[0], 21, 22), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2_PDE2", BITS(stream->words[0], 22, 23), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L1_PTES", BITS(stream->words[0], 23, 24), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "CLEAR_PROTECTION_FAULT_STATUS_ADDR", BITS(stream->words[0], 24, 25), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "LOG_REQUEST", BITS(stream->words[0], 25, 26), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "4KB", BITS(stream->words[0], 26, 27), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 4, ib_vmid, "INV_L2_PDE3", BITS(stream->words[0], 27, 28), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "S_BIT", BITS(stream->words[1], 0, 1), NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 8, ib_vmid, "PAGE_VM_ADDR_LO", BITS(stream->words[1], 1, 32) << 1, NULL, 16, 32);
+			ui->add_field(ui, ib_addr + 12, ib_vmid, "PAGE_VM_ADDR_HI", BITS(stream->words[2], 0, 14), NULL, 16, 32);
+			return;
+		case 17: // GCR
+			switch (stream->sub_opcode) {
+				case 0: // GCR
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GCR", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "BASE_VA_LO", BITS(stream->words[0], 7, 32) << 7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "BASE_VA_HI", BITS(stream->words[1], 0, 16), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "GCR_CONTROL_LO", BITS(stream->words[1], 16, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "GCR_CONTROL_HI", BITS(stream->words[2], 0, 3), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "LIMIT_VA_LO", BITS(stream->words[2], 7, 32) << 7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "LIMIT_VA_HI", BITS(stream->words[3], 0, 16), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "VMID", BITS(stream->words[3], 24, 28), NULL, 16, 32);
+					return;
+				case 1: // GCR user
+					ui->start_opcode(ui, ib_addr, ib_vmid, 0, stream->opcode, stream->sub_opcode, stream->nwords + 1, "GCR USER", stream->header_dw, stream->words);
+					ui->add_field(ui, ib_addr + 4, ib_vmid, "BASE_VA_LO", BITS(stream->words[0], 7, 32) << 7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "BASE_VA_HI", BITS(stream->words[1], 0, 16), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 8, ib_vmid, "GCR_CONTROL_LO", BITS(stream->words[1], 16, 32), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "GCR_CONTROL_HI", BITS(stream->words[2], 0, 3), NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 12, ib_vmid, "LIMIT_VA_LO", BITS(stream->words[2], 7, 32) << 7, NULL, 16, 32);
+					ui->add_field(ui, ib_addr + 16, ib_vmid, "LIMIT_VA_HI", BITS(stream->words[3], 0, 16), NULL, 16, 32);
+					return;
+					return;
+				default:
+					if (ui->unhandled_subop)
+						ui->unhandled_subop(ui, asic, ib_addr, ib_vmid, stream, UMR_RING_SDMA);
+					return;
+			}
+			break;
+	}
+
+	// fall through to NV decoder
+	decode_upto_nv(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, sc);
+}
+
 int umr_sdma_get_ip_ver(struct umr_asic *asic, int *maj, int *min)
 {
 	struct umr_ip_block *ip;
@@ -2243,6 +2933,9 @@ int umr_sdma_get_ip_ver(struct umr_asic *asic, int *maj, int *min)
 				case 11:
 					*maj = 6;
 					break;
+				case 12:
+					*maj = 7;
+					break;
 			}
 			*min = 0;
 			return 0;
@@ -2287,12 +2980,18 @@ struct umr_sdma_stream *umr_sdma_decode_stream_opcodes(struct umr_asic *asic, st
 		switch (sc.ver_maj) {
 			case 1:
 			case 2:
-			case 3: decode_upto_vi(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
+			case 3:
+				decode_upto_vi(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
 				break;
-			case 4: decode_upto_ai(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
+			case 4:
+				decode_upto_ai(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
 				break;
 			case 5:
-			case 6: decode_upto_nv(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
+			case 6:
+				decode_upto_nv(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
+				break;
+			case 7:
+				decode_upto_oss7(asic, ui, stream, ib_addr, ib_vmid, from_addr, from_vmid, follow, &sc);
 				break;
 			default:
 				asic->err_msg("[BUG]: Invalid OSS major version (%d) in SDMA decode\n", sc.ver_maj);
diff --git a/src/umr.h b/src/umr.h
index 75b103bcdfee55388c5190d0de368398ec578b1e..9aada59d5d946a538b314cf54d24a3f43ea43a14 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -106,6 +106,7 @@ enum chipfamily {
 	FAMILY_AI,
 	FAMILY_NV,    // NAVI1X, NAVI2X
 	FAMILY_GFX11,
+	FAMILY_GFX12,
 
 	FAMILY_NPI, // reserves for new devices that are not public yet
 	FAMILY_CONFIGURE,
@@ -376,7 +377,9 @@ typedef struct {
 		further,
 		tfs_addr,
 		llc_noalloc,
-		mtype;
+		mtype,
+		pa_rsvd,
+		mall_reuse;
 } pde_fields_t;
 
 typedef struct {
@@ -397,7 +400,10 @@ typedef struct {
 		pte_mask,
 		gcr,
 		llc_noalloc,
-		software;
+		software,
+		pa_rsvd,
+		dcc,
+		pte;
 } pte_fields_t;
 
 struct umr_memory_access_funcs {
@@ -1604,6 +1610,7 @@ int umr_scan_wave_slot(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t
 		       uint32_t simd, uint32_t wave, struct umr_wave_data *pwd);
 int umr_read_wave_status_via_mmio_gfx8_9(struct umr_asic *asic, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields);
 int umr_read_wave_status_via_mmio_gfx_10_11(struct umr_asic *asic, uint32_t wave, uint32_t *dst, int *no_fields);
+int umr_read_wave_status_via_mmio_gfx_12(struct umr_asic *asic, uint32_t wave, uint32_t *dst, int *no_fields);
 int umr_parse_wave_data_gfx(struct umr_asic *asic, struct umr_wave_status *ws, const uint32_t *buf, uint32_t nwords);
 int umr_get_wave_sq_info_vi(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, struct umr_wave_status *ws);
 int umr_get_wave_sq_info(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, struct umr_wave_status *ws);
@@ -2031,6 +2038,7 @@ enum umr_mqd_engine_sel {
 	UMR_MQD_ENGINE_SDMA0,
 	UMR_MQD_ENGINE_SDMA1,
 	UMR_MQD_ENGINE_GFX,
+	UMR_MQD_ENGINE_MES,
 
 	UMR_MQD_ENGINE_INVALID,
 };