103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2007-2011 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Authors:
2403b705cfSriastradh *    Eric Anholt <eric@anholt.net>
2503b705cfSriastradh *    Chris Wilson <chris@chris-wilson.co.uk>
2603b705cfSriastradh *
2703b705cfSriastradh */
2803b705cfSriastradh
2903b705cfSriastradh#ifdef HAVE_CONFIG_H
3003b705cfSriastradh#include "config.h"
3103b705cfSriastradh#endif
3203b705cfSriastradh
3303b705cfSriastradh#include <sys/mman.h>
3403b705cfSriastradh#include <assert.h>
3503b705cfSriastradh
3603b705cfSriastradh#include "sna.h"
3703b705cfSriastradh#include "sna_reg.h"
3803b705cfSriastradh
3903b705cfSriastradh#include "gen3_render.h"
4003b705cfSriastradh
4103b705cfSriastradh#include "kgem_debug.h"
4203b705cfSriastradh
4303b705cfSriastradhenum type {
4403b705cfSriastradh	T_FLOAT32,
4503b705cfSriastradh	T_FLOAT16,
4603b705cfSriastradh};
4703b705cfSriastradh
4803b705cfSriastradhstatic struct state {
4903b705cfSriastradh	struct vertex_buffer {
5003b705cfSriastradh		int handle;
5103b705cfSriastradh		void *base;
5203b705cfSriastradh		const char *ptr;
5303b705cfSriastradh		int pitch;
5403b705cfSriastradh
5503b705cfSriastradh		struct kgem_bo *current;
5603b705cfSriastradh	} vb;
5703b705cfSriastradh	struct vertex_elements {
5803b705cfSriastradh		int offset;
5903b705cfSriastradh		bool valid;
6003b705cfSriastradh		enum type type;
6103b705cfSriastradh		int size;
6203b705cfSriastradh		uint8_t swizzle[4];
6303b705cfSriastradh	} ve[33];
6403b705cfSriastradh	int num_ve;
6503b705cfSriastradh} state;
6603b705cfSriastradh
6703b705cfSriastradhstatic float int_as_float(int i)
6803b705cfSriastradh{
6903b705cfSriastradh	union {
7003b705cfSriastradh		float f;
7103b705cfSriastradh		int i;
7203b705cfSriastradh	} x;
7303b705cfSriastradh	x.i = i;
7403b705cfSriastradh	return x.f;
7503b705cfSriastradh}
7603b705cfSriastradh
7703b705cfSriastradhstatic void gen3_update_vertex_buffer_addr(struct kgem *kgem,
7803b705cfSriastradh					   uint32_t offset)
7903b705cfSriastradh{
8003b705cfSriastradh	uint32_t handle;
8103b705cfSriastradh	struct kgem_bo *bo = NULL;
8203b705cfSriastradh	void *base, *ptr;
8303b705cfSriastradh	int i;
8403b705cfSriastradh
8503b705cfSriastradh	offset *= sizeof(uint32_t);
8603b705cfSriastradh
8703b705cfSriastradh	for (i = 0; i < kgem->nreloc; i++)
8803b705cfSriastradh		if (kgem->reloc[i].offset == offset)
8903b705cfSriastradh			break;
9003b705cfSriastradh	assert(i < kgem->nreloc);
9103b705cfSriastradh	handle = kgem->reloc[i].target_handle;
9203b705cfSriastradh
9303b705cfSriastradh	if (handle == 0) {
9403b705cfSriastradh		base = kgem->batch;
9503b705cfSriastradh	} else {
9603b705cfSriastradh		list_for_each_entry(bo, &kgem->next_request->buffers, request)
9703b705cfSriastradh			if (bo->handle == handle)
9803b705cfSriastradh				break;
9903b705cfSriastradh		assert(&bo->request != &kgem->next_request->buffers);
10003b705cfSriastradh		base = kgem_bo_map__debug(kgem, bo);
10103b705cfSriastradh	}
10203b705cfSriastradh	ptr = (char *)base + kgem->reloc[i].delta;
10303b705cfSriastradh
10403b705cfSriastradh	state.vb.current = bo;
10503b705cfSriastradh	state.vb.base = base;
10603b705cfSriastradh	state.vb.ptr = ptr;
10703b705cfSriastradh}
10803b705cfSriastradh
10903b705cfSriastradhstatic void gen3_update_vertex_buffer_pitch(struct kgem *kgem,
11003b705cfSriastradh					   uint32_t offset)
11103b705cfSriastradh{
11203b705cfSriastradh	state.vb.pitch = kgem->batch[offset] >> 16 & 0x3f;
11303b705cfSriastradh	state.vb.pitch *= sizeof(uint32_t);
11403b705cfSriastradh}
11503b705cfSriastradh
11603b705cfSriastradhstatic void gen3_update_vertex_elements(struct kgem *kgem, uint32_t data)
11703b705cfSriastradh{
11803b705cfSriastradh	state.ve[1].valid = 1;
11903b705cfSriastradh
12003b705cfSriastradh	switch ((data >> 6) & 7) {
12103b705cfSriastradh	case 1:
12203b705cfSriastradh		state.ve[1].type = T_FLOAT32;
12303b705cfSriastradh		state.ve[1].size = 3;
12403b705cfSriastradh		state.ve[1].swizzle[0] = 1;
12503b705cfSriastradh		state.ve[1].swizzle[1] = 1;
12603b705cfSriastradh		state.ve[1].swizzle[2] = 1;
12703b705cfSriastradh		state.ve[1].swizzle[3] = 3;
12803b705cfSriastradh		break;
12903b705cfSriastradh	case 2:
13003b705cfSriastradh		state.ve[1].type = T_FLOAT32;
13103b705cfSriastradh		state.ve[1].size = 4;
13203b705cfSriastradh		state.ve[1].swizzle[0] = 1;
13303b705cfSriastradh		state.ve[1].swizzle[1] = 1;
13403b705cfSriastradh		state.ve[1].swizzle[2] = 1;
13503b705cfSriastradh		state.ve[1].swizzle[3] = 1;
13603b705cfSriastradh		break;
13703b705cfSriastradh	case 3:
13803b705cfSriastradh		state.ve[1].type = T_FLOAT32;
13903b705cfSriastradh		state.ve[1].size = 2;
14003b705cfSriastradh		state.ve[1].swizzle[0] = 1;
14103b705cfSriastradh		state.ve[1].swizzle[1] = 1;
14203b705cfSriastradh		state.ve[1].swizzle[2] = 2;
14303b705cfSriastradh		state.ve[1].swizzle[3] = 3;
14403b705cfSriastradh		break;
14503b705cfSriastradh	case 4:
14603b705cfSriastradh		state.ve[1].type = T_FLOAT32;
14703b705cfSriastradh		state.ve[1].size = 3;
14803b705cfSriastradh		state.ve[1].swizzle[0] = 1;
14903b705cfSriastradh		state.ve[1].swizzle[1] = 1;
15003b705cfSriastradh		state.ve[1].swizzle[2] = 3;
15103b705cfSriastradh		state.ve[1].swizzle[3] = 1;
15203b705cfSriastradh		break;
15303b705cfSriastradh	}
15403b705cfSriastradh
15503b705cfSriastradh	state.ve[2].valid = 0;
15603b705cfSriastradh	state.ve[3].valid = 0;
15703b705cfSriastradh}
15803b705cfSriastradh
15903b705cfSriastradhstatic void gen3_update_vertex_texcoords(struct kgem *kgem, uint32_t data)
16003b705cfSriastradh{
16103b705cfSriastradh	int id;
16203b705cfSriastradh	for (id = 0; id < 8; id++) {
16303b705cfSriastradh		uint32_t fmt = (data >> (id*4)) & 0xf;
16403b705cfSriastradh		int width;
16503b705cfSriastradh
16603b705cfSriastradh		state.ve[id+4].valid = fmt != 0xf;
16703b705cfSriastradh
16803b705cfSriastradh		width = 0;
16903b705cfSriastradh		switch (fmt) {
17003b705cfSriastradh		case 0:
17103b705cfSriastradh			state.ve[id+4].type = T_FLOAT32;
17203b705cfSriastradh			width = state.ve[id+4].size = 2;
17303b705cfSriastradh			break;
17403b705cfSriastradh		case 1:
17503b705cfSriastradh			state.ve[id+4].type = T_FLOAT32;
17603b705cfSriastradh			width = state.ve[id+4].size = 3;
17703b705cfSriastradh			break;
17803b705cfSriastradh		case 2:
17903b705cfSriastradh			state.ve[id+4].type = T_FLOAT32;
18003b705cfSriastradh			width = state.ve[id+4].size = 4;
18103b705cfSriastradh			break;
18203b705cfSriastradh		case 3:
18303b705cfSriastradh			state.ve[id+4].type = T_FLOAT32;
18403b705cfSriastradh			width = state.ve[id+4].size = 1;
18503b705cfSriastradh			break;
18603b705cfSriastradh		case 4:
18703b705cfSriastradh			state.ve[id+4].type = T_FLOAT16;
18803b705cfSriastradh			width = state.ve[id+4].size = 2;
18903b705cfSriastradh			break;
19003b705cfSriastradh		case 5:
19103b705cfSriastradh			state.ve[id+4].type = T_FLOAT16;
19203b705cfSriastradh			width = state.ve[id+4].size = 4;
19303b705cfSriastradh			break;
19403b705cfSriastradh		}
19503b705cfSriastradh
19603b705cfSriastradh		state.ve[id+4].swizzle[0] = width > 0 ? 1 : 2;
19703b705cfSriastradh		state.ve[id+4].swizzle[1] = width > 1 ? 1 : 2;
19803b705cfSriastradh		state.ve[id+4].swizzle[2] = width > 2 ? 1 : 2;
19903b705cfSriastradh		state.ve[id+4].swizzle[3] = width > 3 ? 1 : 2;
20003b705cfSriastradh	}
20103b705cfSriastradh}
20203b705cfSriastradh
20303b705cfSriastradhstatic void gen3_update_vertex_elements_offsets(struct kgem *kgem)
20403b705cfSriastradh{
20503b705cfSriastradh	int i, offset;
20603b705cfSriastradh
20703b705cfSriastradh	for (i = offset = 0; i < ARRAY_SIZE(state.ve); i++) {
20803b705cfSriastradh		if (!state.ve[i].valid)
20903b705cfSriastradh			continue;
21003b705cfSriastradh
21103b705cfSriastradh		state.ve[i].offset = offset;
21203b705cfSriastradh		offset += 4 * state.ve[i].size;
21303b705cfSriastradh		state.num_ve = i;
21403b705cfSriastradh	}
21503b705cfSriastradh}
21603b705cfSriastradh
21703b705cfSriastradhstatic void vertices_float32_out(const struct vertex_elements *ve, const float *f, int max)
21803b705cfSriastradh{
21903b705cfSriastradh	int c;
22003b705cfSriastradh
22103b705cfSriastradh	ErrorF("(");
22203b705cfSriastradh	for (c = 0; c < max; c++) {
22303b705cfSriastradh		switch (ve->swizzle[c]) {
22403b705cfSriastradh		case 0: ErrorF("#"); break;
22503b705cfSriastradh		case 1: ErrorF("%f", f[c]); break;
22603b705cfSriastradh		case 2: ErrorF("0.0"); break;
22703b705cfSriastradh		case 3: ErrorF("1.0"); break;
22803b705cfSriastradh		case 4: ErrorF("0x1"); break;
22903b705cfSriastradh		case 5: break;
23003b705cfSriastradh		default: ErrorF("?");
23103b705cfSriastradh		}
23203b705cfSriastradh		if (c < max-1)
23303b705cfSriastradh			ErrorF(", ");
23403b705cfSriastradh	}
23503b705cfSriastradh	ErrorF(")");
23603b705cfSriastradh}
23703b705cfSriastradh
23803b705cfSriastradhstatic void ve_out(const struct vertex_elements *ve, const void *ptr)
23903b705cfSriastradh{
24003b705cfSriastradh	switch (ve->type) {
24103b705cfSriastradh	case T_FLOAT32:
24203b705cfSriastradh		vertices_float32_out(ve, ptr, ve->size);
24303b705cfSriastradh		break;
24403b705cfSriastradh	case T_FLOAT16:
24503b705cfSriastradh		//vertices_float16_out(ve, ptr, ve->size);
24603b705cfSriastradh		break;
24703b705cfSriastradh	}
24803b705cfSriastradh}
24903b705cfSriastradh
25003b705cfSriastradhstatic void indirect_vertex_out(struct kgem *kgem, uint32_t v)
25103b705cfSriastradh{
25203b705cfSriastradh	const struct vertex_buffer *vb = &state.vb;
25303b705cfSriastradh	int i = 1;
25403b705cfSriastradh
25503b705cfSriastradh	do {
25603b705cfSriastradh		const struct vertex_elements *ve = &state.ve[i];
25703b705cfSriastradh		const void *ptr = vb->ptr + v * vb->pitch + ve->offset;
25803b705cfSriastradh
25903b705cfSriastradh		if (!ve->valid)
26003b705cfSriastradh			continue;
26103b705cfSriastradh
26203b705cfSriastradh		ve_out(ve, ptr);
26303b705cfSriastradh
26403b705cfSriastradh		while (++i <= state.num_ve && !state.ve[i].valid)
26503b705cfSriastradh			;
26603b705cfSriastradh
26703b705cfSriastradh		if (i <= state.num_ve)
26803b705cfSriastradh			ErrorF(", ");
26903b705cfSriastradh	} while (i <= state.num_ve);
27003b705cfSriastradh}
27103b705cfSriastradh
27203b705cfSriastradhstatic int inline_vertex_out(struct kgem *kgem, void *base)
27303b705cfSriastradh{
27403b705cfSriastradh	const struct vertex_buffer *vb = &state.vb;
27503b705cfSriastradh	int i = 1;
27603b705cfSriastradh
27703b705cfSriastradh	do {
27803b705cfSriastradh		const struct vertex_elements *ve = &state.ve[i];
27903b705cfSriastradh		const void *ptr = (char *)base + ve->offset;
28003b705cfSriastradh
28103b705cfSriastradh		if (!ve->valid)
28203b705cfSriastradh			continue;
28303b705cfSriastradh
28403b705cfSriastradh		ve_out(ve, ptr);
28503b705cfSriastradh
28603b705cfSriastradh		while (++i <= state.num_ve && !state.ve[i].valid)
28703b705cfSriastradh			;
28803b705cfSriastradh
28903b705cfSriastradh		if (i <= state.num_ve)
29003b705cfSriastradh			ErrorF(", ");
29103b705cfSriastradh	} while (i <= state.num_ve);
29203b705cfSriastradh
29303b705cfSriastradh	return vb->pitch;
29403b705cfSriastradh}
29503b705cfSriastradh
29603b705cfSriastradhstatic int
29703b705cfSriastradhgen3_decode_3d_1c(struct kgem *kgem, uint32_t offset)
29803b705cfSriastradh{
29903b705cfSriastradh	uint32_t *data = kgem->batch + offset;
30003b705cfSriastradh	uint32_t opcode;
30103b705cfSriastradh
30203b705cfSriastradh	opcode = (data[0] & 0x00f80000) >> 19;
30303b705cfSriastradh
30403b705cfSriastradh	switch (opcode) {
30503b705cfSriastradh	case 0x11:
30603b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE\n");
30703b705cfSriastradh		return 1;
30803b705cfSriastradh	case 0x10:
30903b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_SCISSOR_ENABLE %s\n",
31003b705cfSriastradh			  data[0]&1?"enabled":"disabled");
31103b705cfSriastradh		return 1;
31203b705cfSriastradh	case 0x01:
31303b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_MAP_COORD_SET_I830\n");
31403b705cfSriastradh		return 1;
31503b705cfSriastradh	case 0x0a:
31603b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_MAP_CUBE_I830\n");
31703b705cfSriastradh		return 1;
31803b705cfSriastradh	case 0x05:
31903b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_MAP_TEX_STREAM_I830\n");
32003b705cfSriastradh		return 1;
32103b705cfSriastradh	}
32203b705cfSriastradh
32303b705cfSriastradh	kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1c opcode = 0x%x\n",
32403b705cfSriastradh		  opcode);
32503b705cfSriastradh	assert(0);
32603b705cfSriastradh	return 1;
32703b705cfSriastradh}
32803b705cfSriastradh
32903b705cfSriastradh/** Sets the string dstname to describe the destination of the PS instruction */
33003b705cfSriastradhstatic void
33103b705cfSriastradhgen3_get_instruction_dst(uint32_t *data, int i, char *dstname, int do_mask)
33203b705cfSriastradh{
33303b705cfSriastradh    uint32_t a0 = data[i];
33403b705cfSriastradh    int dst_nr = (a0 >> 14) & 0xf;
33503b705cfSriastradh    char dstmask[8];
33603b705cfSriastradh    const char *sat;
33703b705cfSriastradh
33803b705cfSriastradh    if (do_mask) {
33903b705cfSriastradh	if (((a0 >> 10) & 0xf) == 0xf) {
34003b705cfSriastradh	    dstmask[0] = 0;
34103b705cfSriastradh	} else {
34203b705cfSriastradh	    int dstmask_index = 0;
34303b705cfSriastradh
34403b705cfSriastradh	    dstmask[dstmask_index++] = '.';
34503b705cfSriastradh	    if (a0 & (1 << 10))
34603b705cfSriastradh		dstmask[dstmask_index++] = 'x';
34703b705cfSriastradh	    if (a0 & (1 << 11))
34803b705cfSriastradh		dstmask[dstmask_index++] = 'y';
34903b705cfSriastradh	    if (a0 & (1 << 12))
35003b705cfSriastradh		dstmask[dstmask_index++] = 'z';
35103b705cfSriastradh	    if (a0 & (1 << 13))
35203b705cfSriastradh		dstmask[dstmask_index++] = 'w';
35303b705cfSriastradh	    dstmask[dstmask_index++] = 0;
35403b705cfSriastradh	}
35503b705cfSriastradh
35603b705cfSriastradh	if (a0 & (1 << 22))
35703b705cfSriastradh	    sat = ".sat";
35803b705cfSriastradh	else
35903b705cfSriastradh	    sat = "";
36003b705cfSriastradh    } else {
36103b705cfSriastradh	dstmask[0] = 0;
36203b705cfSriastradh	sat = "";
36303b705cfSriastradh    }
36403b705cfSriastradh
36503b705cfSriastradh    switch ((a0 >> 19) & 0x7) {
36603b705cfSriastradh    case 0:
36703b705cfSriastradh	    assert(dst_nr <= 15);
36803b705cfSriastradh	sprintf(dstname, "R%d%s%s", dst_nr, dstmask, sat);
36903b705cfSriastradh	break;
37003b705cfSriastradh    case 4:
37103b705cfSriastradh	assert(dst_nr == 0);
37203b705cfSriastradh	sprintf(dstname, "oC%s%s", dstmask, sat);
37303b705cfSriastradh	break;
37403b705cfSriastradh    case 5:
37503b705cfSriastradh	assert(dst_nr == 0);
37603b705cfSriastradh	sprintf(dstname, "oD%s%s",  dstmask, sat);
37703b705cfSriastradh	break;
37803b705cfSriastradh    case 6:
37903b705cfSriastradh	assert(dst_nr <= 3);
38003b705cfSriastradh	sprintf(dstname, "U%d%s%s", dst_nr, dstmask, sat);
38103b705cfSriastradh	break;
38203b705cfSriastradh    default:
38303b705cfSriastradh	sprintf(dstname, "RESERVED");
38403b705cfSriastradh	break;
38503b705cfSriastradh    }
38603b705cfSriastradh}
38703b705cfSriastradh
38803b705cfSriastradhstatic const char *
38903b705cfSriastradhgen3_get_channel_swizzle(uint32_t select)
39003b705cfSriastradh{
39103b705cfSriastradh    switch (select & 0x7) {
39203b705cfSriastradh    case 0:
39303b705cfSriastradh	return (select & 8) ? "-x" : "x";
39403b705cfSriastradh    case 1:
39503b705cfSriastradh	return (select & 8) ? "-y" : "y";
39603b705cfSriastradh    case 2:
39703b705cfSriastradh	return (select & 8) ? "-z" : "z";
39803b705cfSriastradh    case 3:
39903b705cfSriastradh	return (select & 8) ? "-w" : "w";
40003b705cfSriastradh    case 4:
40103b705cfSriastradh	return (select & 8) ? "-0" : "0";
40203b705cfSriastradh    case 5:
40303b705cfSriastradh	return (select & 8) ? "-1" : "1";
40403b705cfSriastradh    default:
40503b705cfSriastradh	return (select & 8) ? "-bad" : "bad";
40603b705cfSriastradh    }
40703b705cfSriastradh}
40803b705cfSriastradh
40903b705cfSriastradhstatic void
41003b705cfSriastradhgen3_get_instruction_src_name(uint32_t src_type, uint32_t src_nr, char *name)
41103b705cfSriastradh{
41203b705cfSriastradh	switch (src_type) {
41303b705cfSriastradh	case 0:
41403b705cfSriastradh		sprintf(name, "R%d", src_nr);
41503b705cfSriastradh		assert(src_nr <= 15);
41603b705cfSriastradh		break;
41703b705cfSriastradh	case 1:
41803b705cfSriastradh		if (src_nr < 8)
41903b705cfSriastradh			sprintf(name, "T%d", src_nr);
42003b705cfSriastradh		else if (src_nr == 8)
42103b705cfSriastradh			sprintf(name, "DIFFUSE");
42203b705cfSriastradh		else if (src_nr == 9)
42303b705cfSriastradh			sprintf(name, "SPECULAR");
42403b705cfSriastradh		else if (src_nr == 10)
42503b705cfSriastradh			sprintf(name, "FOG");
42603b705cfSriastradh		else {
42703b705cfSriastradh			assert(0);
42803b705cfSriastradh			sprintf(name, "RESERVED");
42903b705cfSriastradh		}
43003b705cfSriastradh		break;
43103b705cfSriastradh	case 2:
43203b705cfSriastradh		sprintf(name, "C%d", src_nr);
43303b705cfSriastradh		assert(src_nr <= 31);
43403b705cfSriastradh		break;
43503b705cfSriastradh	case 4:
43603b705cfSriastradh		sprintf(name, "oC");
43703b705cfSriastradh		assert(src_nr == 0);
43803b705cfSriastradh		break;
43903b705cfSriastradh	case 5:
44003b705cfSriastradh		sprintf(name, "oD");
44103b705cfSriastradh		assert(src_nr == 0);
44203b705cfSriastradh		break;
44303b705cfSriastradh	case 6:
44403b705cfSriastradh		sprintf(name, "U%d", src_nr);
44503b705cfSriastradh		assert(src_nr <= 3);
44603b705cfSriastradh		break;
44703b705cfSriastradh	default:
44803b705cfSriastradh		sprintf(name, "RESERVED");
44903b705cfSriastradh		assert(0);
45003b705cfSriastradh		break;
45103b705cfSriastradh	}
45203b705cfSriastradh}
45303b705cfSriastradh
45403b705cfSriastradhstatic void
45503b705cfSriastradhgen3_get_instruction_src0(uint32_t *data, int i, char *srcname)
45603b705cfSriastradh{
45703b705cfSriastradh    uint32_t a0 = data[i];
45803b705cfSriastradh    uint32_t a1 = data[i + 1];
45903b705cfSriastradh    int src_nr = (a0 >> 2) & 0x1f;
46003b705cfSriastradh    const char *swizzle_x = gen3_get_channel_swizzle((a1 >> 28) & 0xf);
46103b705cfSriastradh    const char *swizzle_y = gen3_get_channel_swizzle((a1 >> 24) & 0xf);
46203b705cfSriastradh    const char *swizzle_z = gen3_get_channel_swizzle((a1 >> 20) & 0xf);
46303b705cfSriastradh    const char *swizzle_w = gen3_get_channel_swizzle((a1 >> 16) & 0xf);
46403b705cfSriastradh    char swizzle[100];
46503b705cfSriastradh
46603b705cfSriastradh    gen3_get_instruction_src_name((a0 >> 7) & 0x7, src_nr, srcname);
46703b705cfSriastradh    sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z, swizzle_w);
46803b705cfSriastradh    if (strcmp(swizzle, ".xyzw") != 0)
46903b705cfSriastradh	strcat(srcname, swizzle);
47003b705cfSriastradh}
47103b705cfSriastradh
47203b705cfSriastradhstatic void
47303b705cfSriastradhgen3_get_instruction_src1(uint32_t *data, int i, char *srcname)
47403b705cfSriastradh{
47503b705cfSriastradh    uint32_t a1 = data[i + 1];
47603b705cfSriastradh    uint32_t a2 = data[i + 2];
47703b705cfSriastradh    int src_nr = (a1 >> 8) & 0x1f;
47803b705cfSriastradh    const char *swizzle_x = gen3_get_channel_swizzle((a1 >> 4) & 0xf);
47903b705cfSriastradh    const char *swizzle_y = gen3_get_channel_swizzle((a1 >> 0) & 0xf);
48003b705cfSriastradh    const char *swizzle_z = gen3_get_channel_swizzle((a2 >> 28) & 0xf);
48103b705cfSriastradh    const char *swizzle_w = gen3_get_channel_swizzle((a2 >> 24) & 0xf);
48203b705cfSriastradh    char swizzle[100];
48303b705cfSriastradh
48403b705cfSriastradh    gen3_get_instruction_src_name((a1 >> 13) & 0x7, src_nr, srcname);
48503b705cfSriastradh    sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z, swizzle_w);
48603b705cfSriastradh    if (strcmp(swizzle, ".xyzw") != 0)
48703b705cfSriastradh	strcat(srcname, swizzle);
48803b705cfSriastradh}
48903b705cfSriastradh
49003b705cfSriastradhstatic void
49103b705cfSriastradhgen3_get_instruction_src2(uint32_t *data, int i, char *srcname)
49203b705cfSriastradh{
49303b705cfSriastradh    uint32_t a2 = data[i + 2];
49403b705cfSriastradh    int src_nr = (a2 >> 16) & 0x1f;
49503b705cfSriastradh    const char *swizzle_x = gen3_get_channel_swizzle((a2 >> 12) & 0xf);
49603b705cfSriastradh    const char *swizzle_y = gen3_get_channel_swizzle((a2 >> 8) & 0xf);
49703b705cfSriastradh    const char *swizzle_z = gen3_get_channel_swizzle((a2 >> 4) & 0xf);
49803b705cfSriastradh    const char *swizzle_w = gen3_get_channel_swizzle((a2 >> 0) & 0xf);
49903b705cfSriastradh    char swizzle[100];
50003b705cfSriastradh
50103b705cfSriastradh    gen3_get_instruction_src_name((a2 >> 21) & 0x7, src_nr, srcname);
50203b705cfSriastradh    sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z, swizzle_w);
50303b705cfSriastradh    if (strcmp(swizzle, ".xyzw") != 0)
50403b705cfSriastradh	strcat(srcname, swizzle);
50503b705cfSriastradh}
50603b705cfSriastradh
50703b705cfSriastradhstatic void
50803b705cfSriastradhgen3_get_instruction_addr(uint32_t src_type, uint32_t src_nr, char *name)
50903b705cfSriastradh{
51003b705cfSriastradh	switch (src_type) {
51103b705cfSriastradh	case 0:
51203b705cfSriastradh		sprintf(name, "R%d", src_nr);
51303b705cfSriastradh		assert(src_nr <= 15);
51403b705cfSriastradh		break;
51503b705cfSriastradh	case 1:
51603b705cfSriastradh		if (src_nr < 8)
51703b705cfSriastradh			sprintf(name, "T%d", src_nr);
51803b705cfSriastradh		else if (src_nr == 8)
51903b705cfSriastradh			sprintf(name, "DIFFUSE");
52003b705cfSriastradh		else if (src_nr == 9)
52103b705cfSriastradh			sprintf(name, "SPECULAR");
52203b705cfSriastradh		else if (src_nr == 10)
52303b705cfSriastradh			sprintf(name, "FOG");
52403b705cfSriastradh		else {
52503b705cfSriastradh			assert(0);
52603b705cfSriastradh			sprintf(name, "RESERVED");
52703b705cfSriastradh		}
52803b705cfSriastradh		break;
52903b705cfSriastradh	case 4:
53003b705cfSriastradh		sprintf(name, "oC");
53103b705cfSriastradh		assert(src_nr == 0);
53203b705cfSriastradh		break;
53303b705cfSriastradh	case 5:
53403b705cfSriastradh		sprintf(name, "oD");
53503b705cfSriastradh		assert(src_nr == 0);
53603b705cfSriastradh		break;
53703b705cfSriastradh	default:
53803b705cfSriastradh		assert(0);
53903b705cfSriastradh		sprintf(name, "RESERVED");
54003b705cfSriastradh		break;
54103b705cfSriastradh	}
54203b705cfSriastradh}
54303b705cfSriastradh
54403b705cfSriastradhstatic void
54503b705cfSriastradhgen3_decode_alu1(uint32_t *data, uint32_t offset,
54603b705cfSriastradh		 int i, char *instr_prefix, const char *op_name)
54703b705cfSriastradh{
54803b705cfSriastradh    char dst[100], src0[100];
54903b705cfSriastradh
55003b705cfSriastradh    gen3_get_instruction_dst(data, i, dst, 1);
55103b705cfSriastradh    gen3_get_instruction_src0(data, i, src0);
55203b705cfSriastradh
55303b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s: %s %s, %s\n", instr_prefix,
55403b705cfSriastradh	      op_name, dst, src0);
55503b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
55603b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
55703b705cfSriastradh}
55803b705cfSriastradh
55903b705cfSriastradhstatic void
56003b705cfSriastradhgen3_decode_alu2(uint32_t *data, uint32_t offset,
56103b705cfSriastradh		 int i, char *instr_prefix, const char *op_name)
56203b705cfSriastradh{
56303b705cfSriastradh    char dst[100], src0[100], src1[100];
56403b705cfSriastradh
56503b705cfSriastradh    gen3_get_instruction_dst(data, i, dst, 1);
56603b705cfSriastradh    gen3_get_instruction_src0(data, i, src0);
56703b705cfSriastradh    gen3_get_instruction_src1(data, i, src1);
56803b705cfSriastradh
56903b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s: %s %s, %s, %s\n", instr_prefix,
57003b705cfSriastradh	      op_name, dst, src0, src1);
57103b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
57203b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
57303b705cfSriastradh}
57403b705cfSriastradh
57503b705cfSriastradhstatic void
57603b705cfSriastradhgen3_decode_alu3(uint32_t *data, uint32_t offset,
57703b705cfSriastradh		 int i, char *instr_prefix, const char *op_name)
57803b705cfSriastradh{
57903b705cfSriastradh    char dst[100], src0[100], src1[100], src2[100];
58003b705cfSriastradh
58103b705cfSriastradh    gen3_get_instruction_dst(data, i, dst, 1);
58203b705cfSriastradh    gen3_get_instruction_src0(data, i, src0);
58303b705cfSriastradh    gen3_get_instruction_src1(data, i, src1);
58403b705cfSriastradh    gen3_get_instruction_src2(data, i, src2);
58503b705cfSriastradh
58603b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s: %s %s, %s, %s, %s\n", instr_prefix,
58703b705cfSriastradh	      op_name, dst, src0, src1, src2);
58803b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
58903b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
59003b705cfSriastradh}
59103b705cfSriastradh
59203b705cfSriastradhstatic void
59303b705cfSriastradhgen3_decode_tex(uint32_t *data, uint32_t offset, int i, char *instr_prefix,
59403b705cfSriastradh		const char *tex_name)
59503b705cfSriastradh{
59603b705cfSriastradh    uint32_t t0 = data[i];
59703b705cfSriastradh    uint32_t t1 = data[i + 1];
59803b705cfSriastradh    char dst_name[100];
59903b705cfSriastradh    char addr_name[100];
60003b705cfSriastradh    int sampler_nr;
60103b705cfSriastradh
60203b705cfSriastradh    gen3_get_instruction_dst(data, i, dst_name, 0);
60303b705cfSriastradh    gen3_get_instruction_addr((t1 >> 24) & 0x7,
60403b705cfSriastradh			      (t1 >> 17) & 0xf,
60503b705cfSriastradh			      addr_name);
60603b705cfSriastradh    sampler_nr = t0 & 0xf;
60703b705cfSriastradh
60803b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s: %s %s, S%d, %s\n", instr_prefix,
60903b705cfSriastradh	      tex_name, dst_name, sampler_nr, addr_name);
61003b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
61103b705cfSriastradh    kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
61203b705cfSriastradh}
61303b705cfSriastradh
61403b705cfSriastradhstatic void
61503b705cfSriastradhgen3_decode_dcl(uint32_t *data, uint32_t offset, int i, char *instr_prefix)
61603b705cfSriastradh{
61703b705cfSriastradh	uint32_t d0 = data[i];
61803b705cfSriastradh	const char *sampletype;
61903b705cfSriastradh	int dcl_nr = (d0 >> 14) & 0xf;
62003b705cfSriastradh	const char *dcl_x = d0 & (1 << 10) ? "x" : "";
62103b705cfSriastradh	const char *dcl_y = d0 & (1 << 11) ? "y" : "";
62203b705cfSriastradh	const char *dcl_z = d0 & (1 << 12) ? "z" : "";
62303b705cfSriastradh	const char *dcl_w = d0 & (1 << 13) ? "w" : "";
62403b705cfSriastradh	char dcl_mask[10];
62503b705cfSriastradh
62603b705cfSriastradh	switch ((d0 >> 19) & 0x3) {
62703b705cfSriastradh	case 1:
62803b705cfSriastradh		sprintf(dcl_mask, ".%s%s%s%s", dcl_x, dcl_y, dcl_z, dcl_w);
62903b705cfSriastradh		assert (strcmp(dcl_mask, "."));
63003b705cfSriastradh
63103b705cfSriastradh		assert(dcl_nr <= 10);
63203b705cfSriastradh		if (dcl_nr < 8) {
63303b705cfSriastradh			if (strcmp(dcl_mask, ".x") != 0 &&
63403b705cfSriastradh			    strcmp(dcl_mask, ".xy") != 0 &&
63503b705cfSriastradh			    strcmp(dcl_mask, ".xz") != 0 &&
63603b705cfSriastradh			    strcmp(dcl_mask, ".w") != 0 &&
63703b705cfSriastradh			    strcmp(dcl_mask, ".xyzw") != 0) {
63803b705cfSriastradh				assert(0);
63903b705cfSriastradh			}
64003b705cfSriastradh			kgem_debug_print(data, offset, i++, "%s: DCL T%d%s\n", instr_prefix,
64103b705cfSriastradh				  dcl_nr, dcl_mask);
64203b705cfSriastradh		} else {
64303b705cfSriastradh			if (strcmp(dcl_mask, ".xz") == 0)
64403b705cfSriastradh				assert(0);
64503b705cfSriastradh			else if (strcmp(dcl_mask, ".xw") == 0)
64603b705cfSriastradh				assert(0);
64703b705cfSriastradh			else if (strcmp(dcl_mask, ".xzw") == 0)
64803b705cfSriastradh				assert(0);
64903b705cfSriastradh
65003b705cfSriastradh			if (dcl_nr == 8) {
65103b705cfSriastradh				kgem_debug_print(data, offset, i++, "%s: DCL DIFFUSE%s\n", instr_prefix,
65203b705cfSriastradh					  dcl_mask);
65303b705cfSriastradh			} else if (dcl_nr == 9) {
65403b705cfSriastradh				kgem_debug_print(data, offset, i++, "%s: DCL SPECULAR%s\n", instr_prefix,
65503b705cfSriastradh					  dcl_mask);
65603b705cfSriastradh			} else if (dcl_nr == 10) {
65703b705cfSriastradh				kgem_debug_print(data, offset, i++, "%s: DCL FOG%s\n", instr_prefix,
65803b705cfSriastradh					  dcl_mask);
65903b705cfSriastradh			}
66003b705cfSriastradh		}
66103b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
66203b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
66303b705cfSriastradh		break;
66403b705cfSriastradh	case 3:
66503b705cfSriastradh		switch ((d0 >> 22) & 0x3) {
66603b705cfSriastradh		case 0:
66703b705cfSriastradh			sampletype = "2D";
66803b705cfSriastradh			break;
66903b705cfSriastradh		case 1:
67003b705cfSriastradh			sampletype = "CUBE";
67103b705cfSriastradh			break;
67203b705cfSriastradh		case 2:
67303b705cfSriastradh			sampletype = "3D";
67403b705cfSriastradh			break;
67503b705cfSriastradh		default:
67603b705cfSriastradh			sampletype = "RESERVED";
67703b705cfSriastradh			break;
67803b705cfSriastradh		}
67903b705cfSriastradh		assert(dcl_nr <= 15);
68003b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s: DCL S%d %s\n", instr_prefix,
68103b705cfSriastradh			  dcl_nr, sampletype);
68203b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
68303b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
68403b705cfSriastradh		break;
68503b705cfSriastradh	default:
68603b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s: DCL RESERVED%d\n", instr_prefix, dcl_nr);
68703b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
68803b705cfSriastradh		kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
68903b705cfSriastradh	}
69003b705cfSriastradh}
69103b705cfSriastradh
69203b705cfSriastradhstatic void
69303b705cfSriastradhgen3_decode_instruction(uint32_t *data, uint32_t offset,
69403b705cfSriastradh			int i, char *instr_prefix)
69503b705cfSriastradh{
69603b705cfSriastradh    switch ((data[i] >> 24) & 0x1f) {
69703b705cfSriastradh    case 0x0:
69803b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s: NOP\n", instr_prefix);
69903b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
70003b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
70103b705cfSriastradh	break;
70203b705cfSriastradh    case 0x01:
70303b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "ADD");
70403b705cfSriastradh	break;
70503b705cfSriastradh    case 0x02:
70603b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "MOV");
70703b705cfSriastradh	break;
70803b705cfSriastradh    case 0x03:
70903b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "MUL");
71003b705cfSriastradh	break;
71103b705cfSriastradh    case 0x04:
71203b705cfSriastradh	gen3_decode_alu3(data, offset, i, instr_prefix, "MAD");
71303b705cfSriastradh	break;
71403b705cfSriastradh    case 0x05:
71503b705cfSriastradh	gen3_decode_alu3(data, offset, i, instr_prefix, "DP2ADD");
71603b705cfSriastradh	break;
71703b705cfSriastradh    case 0x06:
71803b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "DP3");
71903b705cfSriastradh	break;
72003b705cfSriastradh    case 0x07:
72103b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "DP4");
72203b705cfSriastradh	break;
72303b705cfSriastradh    case 0x08:
72403b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "FRC");
72503b705cfSriastradh	break;
72603b705cfSriastradh    case 0x09:
72703b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "RCP");
72803b705cfSriastradh	break;
72903b705cfSriastradh    case 0x0a:
73003b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "RSQ");
73103b705cfSriastradh	break;
73203b705cfSriastradh    case 0x0b:
73303b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "EXP");
73403b705cfSriastradh	break;
73503b705cfSriastradh    case 0x0c:
73603b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "LOG");
73703b705cfSriastradh	break;
73803b705cfSriastradh    case 0x0d:
73903b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "CMP");
74003b705cfSriastradh	break;
74103b705cfSriastradh    case 0x0e:
74203b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "MIN");
74303b705cfSriastradh	break;
74403b705cfSriastradh    case 0x0f:
74503b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "MAX");
74603b705cfSriastradh	break;
74703b705cfSriastradh    case 0x10:
74803b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "FLR");
74903b705cfSriastradh	break;
75003b705cfSriastradh    case 0x11:
75103b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "MOD");
75203b705cfSriastradh	break;
75303b705cfSriastradh    case 0x12:
75403b705cfSriastradh	gen3_decode_alu1(data, offset, i, instr_prefix, "TRC");
75503b705cfSriastradh	break;
75603b705cfSriastradh    case 0x13:
75703b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "SGE");
75803b705cfSriastradh	break;
75903b705cfSriastradh    case 0x14:
76003b705cfSriastradh	gen3_decode_alu2(data, offset, i, instr_prefix, "SLT");
76103b705cfSriastradh	break;
76203b705cfSriastradh    case 0x15:
76303b705cfSriastradh	gen3_decode_tex(data, offset, i, instr_prefix, "TEXLD");
76403b705cfSriastradh	break;
76503b705cfSriastradh    case 0x16:
76603b705cfSriastradh	gen3_decode_tex(data, offset, i, instr_prefix, "TEXLDP");
76703b705cfSriastradh	break;
76803b705cfSriastradh    case 0x17:
76903b705cfSriastradh	gen3_decode_tex(data, offset, i, instr_prefix, "TEXLDB");
77003b705cfSriastradh	break;
77103b705cfSriastradh    case 0x19:
77203b705cfSriastradh	gen3_decode_dcl(data, offset, i, instr_prefix);
77303b705cfSriastradh	break;
77403b705cfSriastradh    default:
77503b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s: unknown\n", instr_prefix);
77603b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
77703b705cfSriastradh	kgem_debug_print(data, offset, i++, "%s\n", instr_prefix);
77803b705cfSriastradh	break;
77903b705cfSriastradh    }
78003b705cfSriastradh}
78103b705cfSriastradh
78203b705cfSriastradhstatic const char *
78303b705cfSriastradhgen3_decode_compare_func(uint32_t op)
78403b705cfSriastradh{
78503b705cfSriastradh	switch (op&0x7) {
78603b705cfSriastradh	case 0: return "always";
78703b705cfSriastradh	case 1: return "never";
78803b705cfSriastradh	case 2: return "less";
78903b705cfSriastradh	case 3: return "equal";
79003b705cfSriastradh	case 4: return "lequal";
79103b705cfSriastradh	case 5: return "greater";
79203b705cfSriastradh	case 6: return "notequal";
79303b705cfSriastradh	case 7: return "gequal";
79403b705cfSriastradh	}
79503b705cfSriastradh	return "";
79603b705cfSriastradh}
79703b705cfSriastradh
79803b705cfSriastradhstatic const char *
79903b705cfSriastradhgen3_decode_stencil_op(uint32_t op)
80003b705cfSriastradh{
80103b705cfSriastradh	switch (op&0x7) {
80203b705cfSriastradh	case 0: return "keep";
80303b705cfSriastradh	case 1: return "zero";
80403b705cfSriastradh	case 2: return "replace";
80503b705cfSriastradh	case 3: return "incr_sat";
80603b705cfSriastradh	case 4: return "decr_sat";
80703b705cfSriastradh	case 5: return "greater";
80803b705cfSriastradh	case 6: return "incr";
80903b705cfSriastradh	case 7: return "decr";
81003b705cfSriastradh	}
81103b705cfSriastradh	return "";
81203b705cfSriastradh}
81303b705cfSriastradh
81403b705cfSriastradh#if 0
81503b705cfSriastradh/* part of MODES_4 */
81603b705cfSriastradhstatic const char *
81703b705cfSriastradhgen3_decode_logic_op(uint32_t op)
81803b705cfSriastradh{
81903b705cfSriastradh	switch (op&0xf) {
82003b705cfSriastradh	case 0: return "clear";
82103b705cfSriastradh	case 1: return "nor";
82203b705cfSriastradh	case 2: return "and_inv";
82303b705cfSriastradh	case 3: return "copy_inv";
82403b705cfSriastradh	case 4: return "and_rvrse";
82503b705cfSriastradh	case 5: return "inv";
82603b705cfSriastradh	case 6: return "xor";
82703b705cfSriastradh	case 7: return "nand";
82803b705cfSriastradh	case 8: return "and";
82903b705cfSriastradh	case 9: return "equiv";
83003b705cfSriastradh	case 10: return "noop";
83103b705cfSriastradh	case 11: return "or_inv";
83203b705cfSriastradh	case 12: return "copy";
83303b705cfSriastradh	case 13: return "or_rvrse";
83403b705cfSriastradh	case 14: return "or";
83503b705cfSriastradh	case 15: return "set";
83603b705cfSriastradh	}
83703b705cfSriastradh	return "";
83803b705cfSriastradh}
83903b705cfSriastradh#endif
84003b705cfSriastradh
84103b705cfSriastradhstatic const char *
84203b705cfSriastradhgen3_decode_blend_fact(uint32_t op)
84303b705cfSriastradh{
84403b705cfSriastradh	switch (op&0xf) {
84503b705cfSriastradh	case 1: return "zero";
84603b705cfSriastradh	case 2: return "one";
84703b705cfSriastradh	case 3: return "src_colr";
84803b705cfSriastradh	case 4: return "inv_src_colr";
84903b705cfSriastradh	case 5: return "src_alpha";
85003b705cfSriastradh	case 6: return "inv_src_alpha";
85103b705cfSriastradh	case 7: return "dst_alpha";
85203b705cfSriastradh	case 8: return "inv_dst_alpha";
85303b705cfSriastradh	case 9: return "dst_colr";
85403b705cfSriastradh	case 10: return "inv_dst_colr";
85503b705cfSriastradh	case 11: return "src_alpha_sat";
85603b705cfSriastradh	case 12: return "cnst_colr";
85703b705cfSriastradh	case 13: return "inv_cnst_colr";
85803b705cfSriastradh	case 14: return "cnst_alpha";
85903b705cfSriastradh	case 15: return "inv_const_alpha";
86003b705cfSriastradh	}
86103b705cfSriastradh	return "";
86203b705cfSriastradh}
86303b705cfSriastradh
86403b705cfSriastradhstatic const char *
86503b705cfSriastradhdecode_tex_coord_mode(uint32_t mode)
86603b705cfSriastradh{
86703b705cfSriastradh    switch (mode&0x7) {
86803b705cfSriastradh    case 0: return "wrap";
86903b705cfSriastradh    case 1: return "mirror";
87003b705cfSriastradh    case 2: return "clamp_edge";
87103b705cfSriastradh    case 3: return "cube";
87203b705cfSriastradh    case 4: return "clamp_border";
87303b705cfSriastradh    case 5: return "mirror_once";
87403b705cfSriastradh    }
87503b705cfSriastradh    return "";
87603b705cfSriastradh}
87703b705cfSriastradh
87803b705cfSriastradhstatic const char *
87903b705cfSriastradhgen3_decode_sample_filter(uint32_t mode)
88003b705cfSriastradh{
88103b705cfSriastradh	switch (mode&0x7) {
88203b705cfSriastradh	case 0: return "nearest";
88303b705cfSriastradh	case 1: return "linear";
88403b705cfSriastradh	case 2: return "anisotropic";
88503b705cfSriastradh	case 3: return "4x4_1";
88603b705cfSriastradh	case 4: return "4x4_2";
88703b705cfSriastradh	case 5: return "4x4_flat";
88803b705cfSriastradh	case 6: return "6x5_mono";
88903b705cfSriastradh	}
89003b705cfSriastradh	return "";
89103b705cfSriastradh}
89203b705cfSriastradh
89303b705cfSriastradhstatic int
89403b705cfSriastradhgen3_decode_load_state_immediate_1(struct kgem *kgem, uint32_t offset)
89503b705cfSriastradh{
89603b705cfSriastradh	const uint32_t *data = kgem->batch + offset;
89703b705cfSriastradh	int len, i, word;
89803b705cfSriastradh
89903b705cfSriastradh	kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_1\n");
90003b705cfSriastradh	len = (data[0] & 0x0000000f) + 2;
90103b705cfSriastradh	i = 1;
90203b705cfSriastradh	for (word = 0; word <= 8; word++) {
90303b705cfSriastradh		if (data[0] & (1 << (4 + word))) {
90403b705cfSriastradh			switch (word) {
90503b705cfSriastradh			case 0:
90603b705cfSriastradh				kgem_debug_print(data, offset, i, "S0: vbo offset: 0x%08x%s\n",
90703b705cfSriastradh					  data[i]&(~1),data[i]&1?", auto cache invalidate disabled":"");
90803b705cfSriastradh				gen3_update_vertex_buffer_addr(kgem, offset + i);
90903b705cfSriastradh				break;
91003b705cfSriastradh			case 1:
91103b705cfSriastradh				kgem_debug_print(data, offset, i, "S1: vertex width: %i, vertex pitch: %i\n",
91203b705cfSriastradh					  (data[i]>>24)&0x3f,(data[i]>>16)&0x3f);
91303b705cfSriastradh				gen3_update_vertex_buffer_pitch(kgem, offset + i);
91403b705cfSriastradh				break;
91503b705cfSriastradh			case 2:
91603b705cfSriastradh				{
91703b705cfSriastradh					char buf[200];
91803b705cfSriastradh					int len = 0;
91903b705cfSriastradh					int tex_num;
92003b705cfSriastradh					for (tex_num = 0; tex_num < 8; tex_num++) {
92103b705cfSriastradh						switch((data[i]>>tex_num*4)&0xf) {
92203b705cfSriastradh						case 0: len += sprintf(buf + len, "%i=2D ", tex_num); break;
92303b705cfSriastradh						case 1: len += sprintf(buf + len, "%i=3D ", tex_num); break;
92403b705cfSriastradh						case 2: len += sprintf(buf + len, "%i=4D ", tex_num); break;
92503b705cfSriastradh						case 3: len += sprintf(buf + len, "%i=1D ", tex_num); break;
92603b705cfSriastradh						case 4: len += sprintf(buf + len, "%i=2D_16 ", tex_num); break;
92703b705cfSriastradh						case 5: len += sprintf(buf + len, "%i=4D_16 ", tex_num); break;
92803b705cfSriastradh						case 0xf: len += sprintf(buf + len, "%i=NP ", tex_num); break;
92903b705cfSriastradh						}
93003b705cfSriastradh					}
93103b705cfSriastradh					kgem_debug_print(data, offset, i, "S2: texcoord formats: %s\n", buf);
93203b705cfSriastradh					gen3_update_vertex_texcoords(kgem, data[i]);
93303b705cfSriastradh				}
93403b705cfSriastradh
93503b705cfSriastradh				break;
93603b705cfSriastradh			case 3:
93703b705cfSriastradh				kgem_debug_print(data, offset, i, "S3: not documented\n");
93803b705cfSriastradh				break;
93903b705cfSriastradh			case 4:
94003b705cfSriastradh				{
94103b705cfSriastradh					const char *cullmode = "";
94203b705cfSriastradh					const char *vfmt_xyzw = "";
94303b705cfSriastradh					switch((data[i]>>13)&0x3) {
94403b705cfSriastradh					case 0: cullmode = "both"; break;
94503b705cfSriastradh					case 1: cullmode = "none"; break;
94603b705cfSriastradh					case 2: cullmode = "cw"; break;
94703b705cfSriastradh					case 3: cullmode = "ccw"; break;
94803b705cfSriastradh					}
94903b705cfSriastradh					switch(data[i] & (7<<6 | 1<<2)) {
95003b705cfSriastradh					case 1<<6: vfmt_xyzw = "XYZ,"; break;
95103b705cfSriastradh					case 2<<6: vfmt_xyzw = "XYZW,"; break;
95203b705cfSriastradh					case 3<<6: vfmt_xyzw = "XY,"; break;
95303b705cfSriastradh					case 4<<6: vfmt_xyzw = "XYW,"; break;
95403b705cfSriastradh					case 1<<6 | 1<<2: vfmt_xyzw = "XYZF,"; break;
95503b705cfSriastradh					case 2<<6 | 1<<2: vfmt_xyzw = "XYZWF,"; break;
95603b705cfSriastradh					case 3<<6 | 1<<2: vfmt_xyzw = "XYF,"; break;
95703b705cfSriastradh					case 4<<6 | 1<<2: vfmt_xyzw = "XYWF,"; break;
95803b705cfSriastradh					}
95903b705cfSriastradh					kgem_debug_print(data, offset, i, "S4: point_width=%i, line_width=%.1f,"
96003b705cfSriastradh						  "%s%s%s%s%s cullmode=%s, vfmt=%s%s%s%s%s%s%s%s "
96103b705cfSriastradh						  "%s%s%s\n",
96203b705cfSriastradh						  (data[i]>>23)&0x1ff,
96303b705cfSriastradh						  ((data[i]>>19)&0xf) / 2.0,
96403b705cfSriastradh						  data[i]&(0xf<<15)?" flatshade=":"",
96503b705cfSriastradh						  data[i]&(1<<18)?"Alpha,":"",
96603b705cfSriastradh						  data[i]&(1<<17)?"Fog,":"",
96703b705cfSriastradh						  data[i]&(1<<16)?"Specular,":"",
96803b705cfSriastradh						  data[i]&(1<<15)?"Color,":"",
96903b705cfSriastradh						  cullmode,
97003b705cfSriastradh						  data[i]&(1<<12)?"PointWidth,":"",
97103b705cfSriastradh						  data[i]&(1<<11)?"SpecFog,":"",
97203b705cfSriastradh						  data[i]&(1<<10)?"Color,":"",
97303b705cfSriastradh						  data[i]&(1<<9)?"DepthOfs,":"",
97403b705cfSriastradh						  vfmt_xyzw,
97503b705cfSriastradh						  data[i]&(1<<9)?"FogParam,":"",
97603b705cfSriastradh						  data[i]&(1<<5)?"force default diffuse, ":"",
97703b705cfSriastradh						  data[i]&(1<<4)?"force default specular, ":"",
97803b705cfSriastradh						  data[i]&(1<<3)?"local depth ofs enable, ":"",
97903b705cfSriastradh						  data[i]&(1<<1)?"point sprite enable, ":"",
98003b705cfSriastradh						  data[i]&(1<<0)?"line AA enable, ":"");
98103b705cfSriastradh					gen3_update_vertex_elements(kgem, data[i]);
98203b705cfSriastradh					break;
98303b705cfSriastradh				}
98403b705cfSriastradh			case 5:
98503b705cfSriastradh				{
98603b705cfSriastradh					kgem_debug_print(data, offset, i, "S5:%s%s%s%s%s"
98703b705cfSriastradh						  "%s%s%s%s stencil_ref=0x%x, stencil_test=%s, "
98803b705cfSriastradh						  "stencil_fail=%s, stencil_pass_z_fail=%s, "
98903b705cfSriastradh						  "stencil_pass_z_pass=%s, %s%s%s%s\n",
99003b705cfSriastradh						  data[i]&(0xf<<28)?" write_disable=":"",
99103b705cfSriastradh						  data[i]&(1<<31)?"Alpha,":"",
99203b705cfSriastradh						  data[i]&(1<<30)?"Red,":"",
99303b705cfSriastradh						  data[i]&(1<<29)?"Green,":"",
99403b705cfSriastradh						  data[i]&(1<<28)?"Blue,":"",
99503b705cfSriastradh						  data[i]&(1<<27)?" force default point size,":"",
99603b705cfSriastradh						  data[i]&(1<<26)?" last pixel enable,":"",
99703b705cfSriastradh						  data[i]&(1<<25)?" global depth ofs enable,":"",
99803b705cfSriastradh						  data[i]&(1<<24)?" fog enable,":"",
99903b705cfSriastradh						  (data[i]>>16)&0xff,
100003b705cfSriastradh						  gen3_decode_compare_func(data[i]>>13),
100103b705cfSriastradh						  gen3_decode_stencil_op(data[i]>>10),
100203b705cfSriastradh						  gen3_decode_stencil_op(data[i]>>7),
100303b705cfSriastradh						  gen3_decode_stencil_op(data[i]>>4),
100403b705cfSriastradh						  data[i]&(1<<3)?"stencil write enable, ":"",
100503b705cfSriastradh						  data[i]&(1<<2)?"stencil test enable, ":"",
100603b705cfSriastradh						  data[i]&(1<<1)?"color dither enable, ":"",
100703b705cfSriastradh						  data[i]&(1<<0)?"logicop enable, ":"");
100803b705cfSriastradh				}
100903b705cfSriastradh				break;
101003b705cfSriastradh			case 6:
101103b705cfSriastradh				kgem_debug_print(data, offset, i, "S6: %salpha_test=%s, alpha_ref=0x%x, "
101203b705cfSriastradh					  "depth_test=%s, %ssrc_blnd_fct=%s, dst_blnd_fct=%s, "
101303b705cfSriastradh					  "%s%stristrip_provoking_vertex=%i\n",
101403b705cfSriastradh					  data[i]&(1<<31)?"alpha test enable, ":"",
101503b705cfSriastradh					  gen3_decode_compare_func(data[i]>>28),
101603b705cfSriastradh					  data[i]&(0xff<<20),
101703b705cfSriastradh					  gen3_decode_compare_func(data[i]>>16),
101803b705cfSriastradh					  data[i]&(1<<15)?"cbuf blend enable, ":"",
101903b705cfSriastradh					  gen3_decode_blend_fact(data[i]>>8),
102003b705cfSriastradh					  gen3_decode_blend_fact(data[i]>>4),
102103b705cfSriastradh					  data[i]&(1<<3)?"depth write enable, ":"",
102203b705cfSriastradh					  data[i]&(1<<2)?"cbuf write enable, ":"",
102303b705cfSriastradh					  data[i]&(0x3));
102403b705cfSriastradh				break;
102503b705cfSriastradh			case 7:
102603b705cfSriastradh				kgem_debug_print(data, offset, i, "S7: depth offset constant: 0x%08x\n", data[i]);
102703b705cfSriastradh				break;
102803b705cfSriastradh			}
102903b705cfSriastradh			i++;
103003b705cfSriastradh		}
103103b705cfSriastradh	}
103203b705cfSriastradh
103303b705cfSriastradh	assert(len == i);
103403b705cfSriastradh	return len;
103503b705cfSriastradh}
103603b705cfSriastradh
103703b705cfSriastradhstatic int
103803b705cfSriastradhgen3_decode_3d_1d(struct kgem *kgem, uint32_t offset)
103903b705cfSriastradh{
104003b705cfSriastradh	uint32_t *data = kgem->batch + offset;
104103b705cfSriastradh	unsigned int len, i, c, idx, word, map, sampler, instr;
104203b705cfSriastradh	const char *format, *zformat, *type;
104303b705cfSriastradh	uint32_t opcode;
104403b705cfSriastradh	static const struct {
104503b705cfSriastradh		uint32_t opcode;
104603b705cfSriastradh		int min_len;
104703b705cfSriastradh		int max_len;
104803b705cfSriastradh		const char *name;
104903b705cfSriastradh	} opcodes_3d_1d[] = {
105003b705cfSriastradh		{ 0x86, 4, 4, "3DSTATE_CHROMA_KEY" },
105103b705cfSriastradh		{ 0x88, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
105203b705cfSriastradh		{ 0x99, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
105303b705cfSriastradh		{ 0x9a, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
105403b705cfSriastradh		{ 0x98, 2, 2, "3DSTATE_DEFAULT_Z" },
105503b705cfSriastradh		{ 0x97, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
105603b705cfSriastradh		{ 0x9d, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
105703b705cfSriastradh		{ 0x9e, 4, 4, "3DSTATE_MONO_FILTER" },
105803b705cfSriastradh		{ 0x89, 4, 4, "3DSTATE_FOG_MODE" },
105903b705cfSriastradh		{ 0x8f, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
106003b705cfSriastradh		{ 0x83, 2, 2, "3DSTATE_SPAN_STIPPLE" },
106103b705cfSriastradh	}, *opcode_3d_1d;
106203b705cfSriastradh
106303b705cfSriastradh	opcode = (data[0] & 0x00ff0000) >> 16;
106403b705cfSriastradh
106503b705cfSriastradh	switch (opcode) {
106603b705cfSriastradh	case 0x07:
106703b705cfSriastradh		/* This instruction is unusual.  A 0 length means just 1 DWORD instead of
106803b705cfSriastradh		 * 2.  The 0 length is specified in one place to be unsupported, but
106903b705cfSriastradh		 * stated to be required in another, and 0 length LOAD_INDIRECTs appear
107003b705cfSriastradh		 * to cause no harm at least.
107103b705cfSriastradh		 */
107203b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_INDIRECT\n");
107303b705cfSriastradh		len = (data[0] & 0x000000ff) + 1;
107403b705cfSriastradh		i = 1;
107503b705cfSriastradh		if (data[0] & (0x01 << 8)) {
107603b705cfSriastradh			kgem_debug_print(data, offset, i++, "SIS.0\n");
107703b705cfSriastradh			kgem_debug_print(data, offset, i++, "SIS.1\n");
107803b705cfSriastradh		}
107903b705cfSriastradh		if (data[0] & (0x02 << 8)) {
108003b705cfSriastradh			kgem_debug_print(data, offset, i++, "DIS.0\n");
108103b705cfSriastradh		}
108203b705cfSriastradh		if (data[0] & (0x04 << 8)) {
108303b705cfSriastradh			kgem_debug_print(data, offset, i++, "SSB.0\n");
108403b705cfSriastradh			kgem_debug_print(data, offset, i++, "SSB.1\n");
108503b705cfSriastradh		}
108603b705cfSriastradh		if (data[0] & (0x08 << 8)) {
108703b705cfSriastradh			kgem_debug_print(data, offset, i++, "MSB.0\n");
108803b705cfSriastradh			kgem_debug_print(data, offset, i++, "MSB.1\n");
108903b705cfSriastradh		}
109003b705cfSriastradh		if (data[0] & (0x10 << 8)) {
109103b705cfSriastradh			kgem_debug_print(data, offset, i++, "PSP.0\n");
109203b705cfSriastradh			kgem_debug_print(data, offset, i++, "PSP.1\n");
109303b705cfSriastradh		}
109403b705cfSriastradh		if (data[0] & (0x20 << 8)) {
109503b705cfSriastradh			kgem_debug_print(data, offset, i++, "PSC.0\n");
109603b705cfSriastradh			kgem_debug_print(data, offset, i++, "PSC.1\n");
109703b705cfSriastradh		}
109803b705cfSriastradh		assert(len == i);
109903b705cfSriastradh		return len;
110003b705cfSriastradh	case 0x04:
110103b705cfSriastradh		return gen3_decode_load_state_immediate_1(kgem, offset);
110203b705cfSriastradh	case 0x03:
110303b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_2\n");
110403b705cfSriastradh		len = (data[0] & 0x0000000f) + 2;
110503b705cfSriastradh		i = 1;
110603b705cfSriastradh		for (word = 6; word <= 14; word++) {
110703b705cfSriastradh			if (data[0] & (1 << word)) {
110803b705cfSriastradh				if (word == 6)
110903b705cfSriastradh					kgem_debug_print(data, offset, i++, "TBCF\n");
111003b705cfSriastradh				else if (word >= 7 && word <= 10) {
111103b705cfSriastradh					kgem_debug_print(data, offset, i++, "TB%dC\n", word - 7);
111203b705cfSriastradh					kgem_debug_print(data, offset, i++, "TB%dA\n", word - 7);
111303b705cfSriastradh				} else if (word >= 11 && word <= 14) {
111403b705cfSriastradh					kgem_debug_print(data, offset, i, "TM%dS0: offset=0x%08x, %s\n",
111503b705cfSriastradh						  word - 11,
111603b705cfSriastradh						  data[i]&0xfffffffe,
111703b705cfSriastradh						  data[i]&1?"use fence":"");
111803b705cfSriastradh					i++;
111903b705cfSriastradh					kgem_debug_print(data, offset, i, "TM%dS1: height=%i, width=%i, %s\n",
112003b705cfSriastradh						  word - 11,
112103b705cfSriastradh						  data[i]>>21, (data[i]>>10)&0x3ff,
112203b705cfSriastradh						  data[i]&2?(data[i]&1?"y-tiled":"x-tiled"):"");
112303b705cfSriastradh					i++;
112403b705cfSriastradh					kgem_debug_print(data, offset, i, "TM%dS2: pitch=%i, \n",
112503b705cfSriastradh						  word - 11,
112603b705cfSriastradh						  ((data[i]>>21) + 1)*4);
112703b705cfSriastradh					i++;
112803b705cfSriastradh					kgem_debug_print(data, offset, i++, "TM%dS3\n", word - 11);
112903b705cfSriastradh					kgem_debug_print(data, offset, i++, "TM%dS4: dflt color\n", word - 11);
113003b705cfSriastradh				}
113103b705cfSriastradh			}
113203b705cfSriastradh		}
113303b705cfSriastradh		assert(len == i);
113403b705cfSriastradh		return len;
113503b705cfSriastradh	case 0x00:
113603b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_MAP_STATE\n");
113703b705cfSriastradh		len = (data[0] & 0x0000003f) + 2;
113803b705cfSriastradh		kgem_debug_print(data, offset, 1, "mask\n");
113903b705cfSriastradh
114003b705cfSriastradh		i = 2;
114103b705cfSriastradh		for (map = 0; map <= 15; map++) {
114203b705cfSriastradh			if (data[1] & (1 << map)) {
114303b705cfSriastradh				int width, height, pitch, dword;
114403b705cfSriastradh				struct drm_i915_gem_relocation_entry *reloc;
114503b705cfSriastradh				const char *tiling;
114603b705cfSriastradh
114703b705cfSriastradh				reloc = kgem_debug_get_reloc_entry(kgem, &data[i] - kgem->batch);
114803b705cfSriastradh				assert(reloc->target_handle);
114903b705cfSriastradh
115003b705cfSriastradh				dword = data[i];
115103b705cfSriastradh				kgem_debug_print(data, offset, i++, "map %d MS2 %s%s%s, handle=%d\n", map,
115203b705cfSriastradh					  dword&(1<<31)?"untrusted surface, ":"",
115303b705cfSriastradh					  dword&(1<<1)?"vertical line stride enable, ":"",
115403b705cfSriastradh					  dword&(1<<0)?"vertical ofs enable, ":"",
115503b705cfSriastradh					  reloc->target_handle);
115603b705cfSriastradh
115703b705cfSriastradh				dword = data[i];
115803b705cfSriastradh				width = ((dword >> 10) & ((1 << 11) - 1))+1;
115903b705cfSriastradh				height = ((dword >> 21) & ((1 << 11) - 1))+1;
116003b705cfSriastradh
116103b705cfSriastradh				tiling = "none";
116203b705cfSriastradh				if (dword & (1 << 2))
116303b705cfSriastradh					tiling = "fenced";
116403b705cfSriastradh				else if (dword & (1 << 1))
116503b705cfSriastradh					tiling = dword & (1 << 0) ? "Y" : "X";
116603b705cfSriastradh				type = " BAD";
116703b705cfSriastradh				format = " (invalid)";
116803b705cfSriastradh				switch ((dword>>7) & 0x7) {
116903b705cfSriastradh				case 1:
117003b705cfSriastradh					type = "8";
117103b705cfSriastradh					switch ((dword>>3) & 0xf) {
117203b705cfSriastradh					case 0: format = "I"; break;
117303b705cfSriastradh					case 1: format = "L"; break;
117403b705cfSriastradh					case 4: format = "A"; break;
117503b705cfSriastradh					case 5: format = " mono"; break;
117603b705cfSriastradh					}
117703b705cfSriastradh					break;
117803b705cfSriastradh				case 2:
117903b705cfSriastradh					type = "16";
118003b705cfSriastradh					switch ((dword>>3) & 0xf) {
118103b705cfSriastradh					case 0: format = " rgb565"; break;
118203b705cfSriastradh					case 1: format = " argb1555"; break;
118303b705cfSriastradh					case 2: format = " argb4444"; break;
118403b705cfSriastradh					case 3: format = " ay88"; break;
118503b705cfSriastradh					case 5: format = " 88dvdu"; break;
118603b705cfSriastradh					case 6: format = " bump655"; break;
118703b705cfSriastradh					case 7: format = "I"; break;
118803b705cfSriastradh					case 8: format = "L"; break;
118903b705cfSriastradh					case 9: format = "A"; break;
119003b705cfSriastradh					}
119103b705cfSriastradh					break;
119203b705cfSriastradh				case 3:
119303b705cfSriastradh					type = "32";
119403b705cfSriastradh					switch ((dword>>3) & 0xf) {
119503b705cfSriastradh					case 0: format = " argb8888"; break;
119603b705cfSriastradh					case 1: format = " abgr8888"; break;
119703b705cfSriastradh					case 2: format = " xrgb8888"; break;
119803b705cfSriastradh					case 3: format = " xbgr8888"; break;
119903b705cfSriastradh					case 4: format = " qwvu8888"; break;
120003b705cfSriastradh					case 5: format = " axvu8888"; break;
120103b705cfSriastradh					case 6: format = " lxvu8888"; break;
120203b705cfSriastradh					case 7: format = " xlvu8888"; break;
120303b705cfSriastradh					case 8: format = " argb2101010"; break;
120403b705cfSriastradh					case 9: format = " abgr2101010"; break;
120503b705cfSriastradh					case 10: format = " awvu2101010"; break;
120603b705cfSriastradh					case 11: format = " gr1616"; break;
120703b705cfSriastradh					case 12: format = " vu1616"; break;
120803b705cfSriastradh					case 13: format = " xI824"; break;
120903b705cfSriastradh					case 14: format = " xA824"; break;
121003b705cfSriastradh					case 15: format = " xL824"; break;
121103b705cfSriastradh					}
121203b705cfSriastradh					break;
121303b705cfSriastradh				case 5:
121403b705cfSriastradh					type = "422";
121503b705cfSriastradh					switch ((dword>>3) & 0xf) {
121603b705cfSriastradh					case 0: format = " yuv_swapy"; break;
121703b705cfSriastradh					case 1: format = " yuv"; break;
121803b705cfSriastradh					case 2: format = " yuv_swapuv"; break;
121903b705cfSriastradh					case 3: format = " yuv_swapuvy"; break;
122003b705cfSriastradh					}
122103b705cfSriastradh					break;
122203b705cfSriastradh				case 6:
122303b705cfSriastradh					type = "compressed";
122403b705cfSriastradh					switch ((dword>>3) & 0x7) {
122503b705cfSriastradh					case 0: format = " dxt1"; break;
122603b705cfSriastradh					case 1: format = " dxt2_3"; break;
122703b705cfSriastradh					case 2: format = " dxt4_5"; break;
122803b705cfSriastradh					case 3: format = " fxt1"; break;
122903b705cfSriastradh					case 4: format = " dxt1_rb"; break;
123003b705cfSriastradh					}
123103b705cfSriastradh					break;
123203b705cfSriastradh				case 7:
123303b705cfSriastradh					type = "4b indexed";
123403b705cfSriastradh					switch ((dword>>3) & 0xf) {
123503b705cfSriastradh					case 7: format = " argb8888"; break;
123603b705cfSriastradh					}
123703b705cfSriastradh					break;
123803b705cfSriastradh				default:
123903b705cfSriastradh					format = "BAD";
124003b705cfSriastradh					break;
124103b705cfSriastradh				}
124203b705cfSriastradh				dword = data[i];
124303b705cfSriastradh				kgem_debug_print(data, offset, i++, "map %d MS3 [width=%d, height=%d, format=%s%s, tiling=%s%s]\n",
124403b705cfSriastradh					  map, width, height, type, format, tiling,
124503b705cfSriastradh					  dword&(1<<9)?" palette select":"");
124603b705cfSriastradh
124703b705cfSriastradh				dword = data[i];
124803b705cfSriastradh				pitch = 4*(((dword >> 21) & ((1 << 11) - 1))+1);
124903b705cfSriastradh				kgem_debug_print(data, offset, i++, "map %d MS4 [pitch=%d, max_lod=%i, vol_depth=%i, cube_face_ena=%x, %s]\n",
125003b705cfSriastradh					  map, pitch,
125103b705cfSriastradh					  (dword>>9)&0x3f, dword&0xff, (dword>>15)&0x3f,
125203b705cfSriastradh					  dword&(1<<8)?"miplayout legacy":"miplayout right");
125303b705cfSriastradh			}
125403b705cfSriastradh		}
125503b705cfSriastradh		assert(len == i);
125603b705cfSriastradh		return len;
125703b705cfSriastradh	case 0x06:
125803b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_PIXEL_SHADER_CONSTANTS\n");
125903b705cfSriastradh		len = (data[0] & 0x000000ff) + 2;
126003b705cfSriastradh
126103b705cfSriastradh		i = 2;
126203b705cfSriastradh		for (c = 0; c <= 31; c++) {
126303b705cfSriastradh			if (data[1] & (1 << c)) {
126403b705cfSriastradh				kgem_debug_print(data, offset, i, "C%d.X = %f\n",
126503b705cfSriastradh					  c, int_as_float(data[i]));
126603b705cfSriastradh				i++;
126703b705cfSriastradh				kgem_debug_print(data, offset, i, "C%d.Y = %f\n",
126803b705cfSriastradh					  c, int_as_float(data[i]));
126903b705cfSriastradh				i++;
127003b705cfSriastradh				kgem_debug_print(data, offset, i, "C%d.Z = %f\n",
127103b705cfSriastradh					  c, int_as_float(data[i]));
127203b705cfSriastradh				i++;
127303b705cfSriastradh				kgem_debug_print(data, offset, i, "C%d.W = %f\n",
127403b705cfSriastradh					  c, int_as_float(data[i]));
127503b705cfSriastradh				i++;
127603b705cfSriastradh			}
127703b705cfSriastradh		}
127803b705cfSriastradh		assert(len == i);
127903b705cfSriastradh		return len;
128003b705cfSriastradh	case 0x05:
128103b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_PIXEL_SHADER_PROGRAM\n");
128203b705cfSriastradh		len = (data[0] & 0x000000ff) + 2;
128303b705cfSriastradh		assert(((len-1) % 3) == 0);
128403b705cfSriastradh		assert(len <= 370);
128503b705cfSriastradh		i = 1;
128603b705cfSriastradh		for (instr = 0; instr < (len - 1) / 3; instr++) {
128703b705cfSriastradh			char instr_prefix[10];
128803b705cfSriastradh
128903b705cfSriastradh			sprintf(instr_prefix, "PS%03d", instr);
129003b705cfSriastradh			gen3_decode_instruction(data, offset, i, instr_prefix);
129103b705cfSriastradh			i += 3;
129203b705cfSriastradh		}
129303b705cfSriastradh		return len;
129403b705cfSriastradh	case 0x01:
129503b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DSTATE_SAMPLER_STATE\n");
129603b705cfSriastradh		kgem_debug_print(data, offset, 1, "mask\n");
129703b705cfSriastradh		len = (data[0] & 0x0000003f) + 2;
129803b705cfSriastradh		i = 2;
129903b705cfSriastradh		for (sampler = 0; sampler <= 15; sampler++) {
130003b705cfSriastradh			if (data[1] & (1 << sampler)) {
130103b705cfSriastradh				uint32_t dword;
130203b705cfSriastradh				const char *mip_filter = "";
130303b705cfSriastradh				dword = data[i];
130403b705cfSriastradh				switch ((dword>>20)&0x3) {
130503b705cfSriastradh				case 0: mip_filter = "none"; break;
130603b705cfSriastradh				case 1: mip_filter = "nearest"; break;
130703b705cfSriastradh				case 3: mip_filter = "linear"; break;
130803b705cfSriastradh				}
130903b705cfSriastradh				kgem_debug_print(data, offset, i++, "sampler %d SS2:%s%s%s "
131003b705cfSriastradh					  "base_mip_level=%i, mip_filter=%s, mag_filter=%s, min_filter=%s "
131103b705cfSriastradh					  "lod_bias=%.2f,%s max_aniso=%i, shadow_func=%s\n", sampler,
131203b705cfSriastradh					  dword&(1<<31)?" reverse gamma,":"",
131303b705cfSriastradh					  dword&(1<<30)?" packed2planar,":"",
131403b705cfSriastradh					  dword&(1<<29)?" colorspace conversion,":"",
131503b705cfSriastradh					  (dword>>22)&0x1f,
131603b705cfSriastradh					  mip_filter,
131703b705cfSriastradh					  gen3_decode_sample_filter(dword>>17),
131803b705cfSriastradh					  gen3_decode_sample_filter(dword>>14),
131903b705cfSriastradh					  ((dword>>5)&0x1ff)/(0x10*1.0),
132003b705cfSriastradh					  dword&(1<<4)?" shadow,":"",
132103b705cfSriastradh					  dword&(1<<3)?4:2,
132203b705cfSriastradh					  gen3_decode_compare_func(dword));
132303b705cfSriastradh				dword = data[i];
132403b705cfSriastradh				kgem_debug_print(data, offset, i++, "sampler %d SS3: min_lod=%.2f,%s "
132503b705cfSriastradh					  "tcmode_x=%s, tcmode_y=%s, tcmode_z=%s,%s texmap_idx=%i,%s\n",
132603b705cfSriastradh					  sampler, ((dword>>24)&0xff)/(0x10*1.0),
132703b705cfSriastradh					  dword&(1<<17)?" kill pixel enable,":"",
132803b705cfSriastradh					  decode_tex_coord_mode(dword>>12),
132903b705cfSriastradh					  decode_tex_coord_mode(dword>>9),
133003b705cfSriastradh					  decode_tex_coord_mode(dword>>6),
133103b705cfSriastradh					  dword&(1<<5)?" normalized coords,":"",
133203b705cfSriastradh					  (dword>>1)&0xf,
133303b705cfSriastradh					  dword&(1<<0)?" deinterlacer,":"");
133403b705cfSriastradh				kgem_debug_print(data, offset, i++, "sampler %d SS4: border color\n",
133503b705cfSriastradh					  sampler);
133603b705cfSriastradh			}
133703b705cfSriastradh		}
133803b705cfSriastradh		assert(len == i);
133903b705cfSriastradh		return len;
134003b705cfSriastradh	case 0x85:
134103b705cfSriastradh		len = (data[0] & 0x0000000f) + 2;
134203b705cfSriastradh		assert(len == 2);
134303b705cfSriastradh
134403b705cfSriastradh		kgem_debug_print(data, offset, 0,
134503b705cfSriastradh			  "3DSTATE_DEST_BUFFER_VARIABLES\n");
134603b705cfSriastradh
134703b705cfSriastradh		switch ((data[1] >> 8) & 0xf) {
134803b705cfSriastradh		case 0x0: format = "g8"; break;
134903b705cfSriastradh		case 0x1: format = "x1r5g5b5"; break;
135003b705cfSriastradh		case 0x2: format = "r5g6b5"; break;
135103b705cfSriastradh		case 0x3: format = "a8r8g8b8"; break;
135203b705cfSriastradh		case 0x4: format = "ycrcb_swapy"; break;
135303b705cfSriastradh		case 0x5: format = "ycrcb_normal"; break;
135403b705cfSriastradh		case 0x6: format = "ycrcb_swapuv"; break;
135503b705cfSriastradh		case 0x7: format = "ycrcb_swapuvy"; break;
135603b705cfSriastradh		case 0x8: format = "a4r4g4b4"; break;
135703b705cfSriastradh		case 0x9: format = "a1r5g5b5"; break;
135803b705cfSriastradh		case 0xa: format = "a2r10g10b10"; break;
135903b705cfSriastradh		default: format = "BAD"; break;
136003b705cfSriastradh		}
136103b705cfSriastradh		switch ((data[1] >> 2) & 0x3) {
136203b705cfSriastradh		case 0x0: zformat = "u16"; break;
136303b705cfSriastradh		case 0x1: zformat = "f16"; break;
136403b705cfSriastradh		case 0x2: zformat = "u24x8"; break;
136503b705cfSriastradh		default: zformat = "BAD"; break;
136603b705cfSriastradh		}
136703b705cfSriastradh		kgem_debug_print(data, offset, 1, "%s format, %s depth format, early Z %sabled\n",
136803b705cfSriastradh			  format, zformat,
136903b705cfSriastradh			  (data[1] & (1 << 31)) ? "en" : "dis");
137003b705cfSriastradh		return len;
137103b705cfSriastradh
137203b705cfSriastradh	case 0x8e:
137303b705cfSriastradh		{
137403b705cfSriastradh			const char *name, *tiling;
137503b705cfSriastradh
137603b705cfSriastradh			len = (data[0] & 0x0000000f) + 2;
137703b705cfSriastradh			assert(len == 3);
137803b705cfSriastradh
137903b705cfSriastradh			switch((data[1] >> 24) & 0x7) {
138003b705cfSriastradh			case 0x3: name = "color"; break;
138103b705cfSriastradh			case 0x7: name = "depth"; break;
138203b705cfSriastradh			default: name = "unknown"; break;
138303b705cfSriastradh			}
138403b705cfSriastradh
138503b705cfSriastradh			tiling = "none";
138603b705cfSriastradh			if (data[1] & (1 << 23))
138703b705cfSriastradh				tiling = "fenced";
138803b705cfSriastradh			else if (data[1] & (1 << 22))
138903b705cfSriastradh				tiling = data[1] & (1 << 21) ? "Y" : "X";
139003b705cfSriastradh
139103b705cfSriastradh			kgem_debug_print(data, offset, 0, "3DSTATE_BUFFER_INFO\n");
139203b705cfSriastradh			kgem_debug_print(data, offset, 1, "%s, tiling = %s, pitch=%d\n", name, tiling, data[1]&0xffff);
139303b705cfSriastradh
139403b705cfSriastradh			kgem_debug_print(data, offset, 2, "address\n");
139503b705cfSriastradh			return len;
139603b705cfSriastradh		}
139703b705cfSriastradh	case 0x81:
139803b705cfSriastradh		len = (data[0] & 0x0000000f) + 2;
139903b705cfSriastradh		assert(len == 3);
140003b705cfSriastradh
140103b705cfSriastradh		kgem_debug_print(data, offset, 0,
140203b705cfSriastradh			  "3DSTATE_SCISSOR_RECTANGLE\n");
140303b705cfSriastradh		kgem_debug_print(data, offset, 1, "(%d,%d)\n",
140403b705cfSriastradh			  data[1] & 0xffff, data[1] >> 16);
140503b705cfSriastradh		kgem_debug_print(data, offset, 2, "(%d,%d)\n",
140603b705cfSriastradh			  data[2] & 0xffff, data[2] >> 16);
140703b705cfSriastradh
140803b705cfSriastradh		return len;
140903b705cfSriastradh	case 0x80:
141003b705cfSriastradh		len = (data[0] & 0x0000000f) + 2;
141103b705cfSriastradh		assert(len == 5);
141203b705cfSriastradh
141303b705cfSriastradh		kgem_debug_print(data, offset, 0,
141403b705cfSriastradh			  "3DSTATE_DRAWING_RECTANGLE\n");
141503b705cfSriastradh		kgem_debug_print(data, offset, 1, "%s\n",
141603b705cfSriastradh			  data[1]&(1<<30)?"depth ofs disabled ":"");
141703b705cfSriastradh		kgem_debug_print(data, offset, 2, "(%d,%d)\n",
141803b705cfSriastradh			  data[2] & 0xffff, data[2] >> 16);
141903b705cfSriastradh		kgem_debug_print(data, offset, 3, "(%d,%d)\n",
142003b705cfSriastradh			  data[3] & 0xffff, data[3] >> 16);
142103b705cfSriastradh		kgem_debug_print(data, offset, 4, "(%d,%d)\n",
142203b705cfSriastradh			  (int16_t)(data[4] & 0xffff),
142303b705cfSriastradh			  (int16_t)(data[4] >> 16));
142403b705cfSriastradh
142503b705cfSriastradh		return len;
142603b705cfSriastradh	case 0x9c:
142703b705cfSriastradh		len = (data[0] & 0x0000000f) + 2;
142803b705cfSriastradh		assert(len == 7);
142903b705cfSriastradh
143003b705cfSriastradh		kgem_debug_print(data, offset, 0,
143103b705cfSriastradh			  "3DSTATE_CLEAR_PARAMETERS\n");
143203b705cfSriastradh		kgem_debug_print(data, offset, 1, "prim_type=%s, clear=%s%s%s\n",
143303b705cfSriastradh			  data[1]&(1<<16)?"CLEAR_RECT":"ZONE_INIT",
143403b705cfSriastradh			  data[1]&(1<<2)?"color,":"",
143503b705cfSriastradh			  data[1]&(1<<1)?"depth,":"",
143603b705cfSriastradh			  data[1]&(1<<0)?"stencil,":"");
143703b705cfSriastradh		kgem_debug_print(data, offset, 2, "clear color\n");
143803b705cfSriastradh		kgem_debug_print(data, offset, 3, "clear depth/stencil\n");
143903b705cfSriastradh		kgem_debug_print(data, offset, 4, "color value (rgba8888)\n");
144003b705cfSriastradh		kgem_debug_print(data, offset, 5, "depth value %f\n",
144103b705cfSriastradh			  int_as_float(data[5]));
144203b705cfSriastradh		kgem_debug_print(data, offset, 6, "clear stencil\n");
144303b705cfSriastradh		return len;
144403b705cfSriastradh	}
144503b705cfSriastradh
144603b705cfSriastradh	for (idx = 0; idx < ARRAY_SIZE(opcodes_3d_1d); idx++) {
144703b705cfSriastradh		opcode_3d_1d = &opcodes_3d_1d[idx];
144803b705cfSriastradh		if (((data[0] & 0x00ff0000) >> 16) == opcode_3d_1d->opcode) {
144903b705cfSriastradh			len = (data[0] & 0xf) + 2;
145003b705cfSriastradh			kgem_debug_print(data, offset, 0, "%s\n", opcode_3d_1d->name);
145103b705cfSriastradh			for (i = 1; i < len; i++)
145203b705cfSriastradh				kgem_debug_print(data, offset, i, "dword %d\n", i);
145303b705cfSriastradh
145403b705cfSriastradh			return len;
145503b705cfSriastradh		}
145603b705cfSriastradh	}
145703b705cfSriastradh
145803b705cfSriastradh	kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1d opcode = 0x%x\n", opcode);
145903b705cfSriastradh	assert(0);
146003b705cfSriastradh	return 1;
146103b705cfSriastradh}
146203b705cfSriastradh
146303b705cfSriastradh#define VERTEX_OUT(fmt, ...) do {					\
146403b705cfSriastradh	kgem_debug_print(data, offset, i, " V%d."fmt"\n", vertex, __VA_ARGS__); \
146503b705cfSriastradh	i++;								\
146603b705cfSriastradh} while (0)
146703b705cfSriastradh
146803b705cfSriastradhstatic int
146903b705cfSriastradhgen3_decode_3d_primitive(struct kgem *kgem, uint32_t offset)
147003b705cfSriastradh{
147103b705cfSriastradh	uint32_t *data = kgem->batch + offset;
147203b705cfSriastradh	char immediate = (data[0] & (1 << 23)) == 0;
147303b705cfSriastradh	unsigned int len, i, ret;
147403b705cfSriastradh	const char *primtype;
147503b705cfSriastradh	unsigned int vertex = 0;
147603b705cfSriastradh
147703b705cfSriastradh	switch ((data[0] >> 18) & 0xf) {
147803b705cfSriastradh	case 0x0: primtype = "TRILIST"; break;
147903b705cfSriastradh	case 0x1: primtype = "TRISTRIP"; break;
148003b705cfSriastradh	case 0x2: primtype = "TRISTRIP_REVERSE"; break;
148103b705cfSriastradh	case 0x3: primtype = "TRIFAN"; break;
148203b705cfSriastradh	case 0x4: primtype = "POLYGON"; break;
148303b705cfSriastradh	case 0x5: primtype = "LINELIST"; break;
148403b705cfSriastradh	case 0x6: primtype = "LINESTRIP"; break;
148503b705cfSriastradh	case 0x7: primtype = "RECTLIST"; break;
148603b705cfSriastradh	case 0x8: primtype = "POINTLIST"; break;
148703b705cfSriastradh	case 0x9: primtype = "DIB"; break;
148803b705cfSriastradh	case 0xa: primtype = "CLEAR_RECT"; assert(0); break;
148903b705cfSriastradh	default: primtype = "unknown"; break;
149003b705cfSriastradh	}
149103b705cfSriastradh
149203b705cfSriastradh	gen3_update_vertex_elements_offsets(kgem);
149303b705cfSriastradh
149403b705cfSriastradh	/* XXX: 3DPRIM_DIB not supported */
149503b705cfSriastradh	if (immediate) {
149603b705cfSriastradh		len = (data[0] & 0x0003ffff) + 2;
149703b705cfSriastradh		kgem_debug_print(data, offset, 0, "3DPRIMITIVE inline %s\n", primtype);
149803b705cfSriastradh		for (i = 1; i < len; ) {
149903b705cfSriastradh			ErrorF("    [%d]: ", vertex);
150003b705cfSriastradh			i += inline_vertex_out(kgem, data + i) / sizeof(uint32_t);
150103b705cfSriastradh			ErrorF("\n");
150203b705cfSriastradh			vertex++;
150303b705cfSriastradh		}
150403b705cfSriastradh
150503b705cfSriastradh		ret = len;
150603b705cfSriastradh	} else {
150703b705cfSriastradh		/* indirect vertices */
150803b705cfSriastradh		len = data[0] & 0x0000ffff; /* index count */
150903b705cfSriastradh		if (data[0] & (1 << 17)) {
151003b705cfSriastradh			/* random vertex access */
151103b705cfSriastradh			kgem_debug_print(data, offset, 0,
151203b705cfSriastradh				  "3DPRIMITIVE random indirect %s (%d)\n", primtype, len);
151303b705cfSriastradh			assert(0);
151403b705cfSriastradh			if (len == 0) {
151503b705cfSriastradh				/* vertex indices continue until 0xffff is found */
151603b705cfSriastradh			} else {
151703b705cfSriastradh				/* fixed size vertex index buffer */
151803b705cfSriastradh			}
151903b705cfSriastradh			ret = (len + 1) / 2 + 1;
152003b705cfSriastradh			goto out;
152103b705cfSriastradh		} else {
152203b705cfSriastradh			/* sequential vertex access */
152303b705cfSriastradh			vertex = data[1] & 0xffff;
152403b705cfSriastradh			kgem_debug_print(data, offset, 0,
152503b705cfSriastradh				  "3DPRIMITIVE sequential indirect %s, %d starting from "
152603b705cfSriastradh				  "%d\n", primtype, len, vertex);
152703b705cfSriastradh			kgem_debug_print(data, offset, 1, "  start\n");
152803b705cfSriastradh			for (i = 0; i < len; i++) {
152903b705cfSriastradh				ErrorF("    [%d]: ", vertex);
153003b705cfSriastradh				indirect_vertex_out(kgem, vertex++);
153103b705cfSriastradh				ErrorF("\n");
153203b705cfSriastradh			}
153303b705cfSriastradh			ret = 2;
153403b705cfSriastradh			goto out;
153503b705cfSriastradh		}
153603b705cfSriastradh	}
153703b705cfSriastradh
153803b705cfSriastradhout:
153903b705cfSriastradh	return ret;
154003b705cfSriastradh}
154103b705cfSriastradh
154203b705cfSriastradhint kgem_gen3_decode_3d(struct kgem *kgem, uint32_t offset)
154303b705cfSriastradh{
154403b705cfSriastradh    static const struct {
154503b705cfSriastradh	uint32_t opcode;
154603b705cfSriastradh	int min_len;
154703b705cfSriastradh	int max_len;
154803b705cfSriastradh	const char *name;
154903b705cfSriastradh    } opcodes[] = {
155003b705cfSriastradh	{ 0x06, 1, 1, "3DSTATE_ANTI_ALIASING" },
155103b705cfSriastradh	{ 0x08, 1, 1, "3DSTATE_BACKFACE_STENCIL_OPS" },
155203b705cfSriastradh	{ 0x09, 1, 1, "3DSTATE_BACKFACE_STENCIL_MASKS" },
155303b705cfSriastradh	{ 0x16, 1, 1, "3DSTATE_COORD_SET_BINDINGS" },
155403b705cfSriastradh	{ 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
155503b705cfSriastradh	{ 0x0b, 1, 1, "3DSTATE_INDEPENDENT_ALPHA_BLEND" },
155603b705cfSriastradh	{ 0x0d, 1, 1, "3DSTATE_MODES_4" },
155703b705cfSriastradh	{ 0x0c, 1, 1, "3DSTATE_MODES_5" },
155803b705cfSriastradh	{ 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
155903b705cfSriastradh    };
156003b705cfSriastradh    uint32_t *data = kgem->batch + offset;
156103b705cfSriastradh    uint32_t opcode;
156203b705cfSriastradh    unsigned int idx;
156303b705cfSriastradh
156403b705cfSriastradh    opcode = (data[0] & 0x1f000000) >> 24;
156503b705cfSriastradh
156603b705cfSriastradh    switch (opcode) {
156703b705cfSriastradh    case 0x1f:
156803b705cfSriastradh	return gen3_decode_3d_primitive(kgem, offset);
156903b705cfSriastradh    case 0x1d:
157003b705cfSriastradh	return gen3_decode_3d_1d(kgem, offset);
157103b705cfSriastradh    case 0x1c:
157203b705cfSriastradh	return gen3_decode_3d_1c(kgem, offset);
157303b705cfSriastradh    }
157403b705cfSriastradh
157503b705cfSriastradh    for (idx = 0; idx < ARRAY_SIZE(opcodes); idx++) {
157603b705cfSriastradh	if (opcode == opcodes[idx].opcode) {
157703b705cfSriastradh	    unsigned int len = 1, i;
157803b705cfSriastradh
157903b705cfSriastradh	    kgem_debug_print(data, offset, 0, "%s\n", opcodes[idx].name);
158003b705cfSriastradh	    if (opcodes[idx].max_len > 1) {
158103b705cfSriastradh		len = (data[0] & 0xff) + 2;
158203b705cfSriastradh		assert(len >= opcodes[idx].min_len ||
158303b705cfSriastradh		       len <= opcodes[idx].max_len);
158403b705cfSriastradh	    }
158503b705cfSriastradh
158603b705cfSriastradh	    for (i = 1; i < len; i++)
158703b705cfSriastradh		kgem_debug_print(data, offset, i, "dword %d\n", i);
158803b705cfSriastradh	    return len;
158903b705cfSriastradh	}
159003b705cfSriastradh    }
159103b705cfSriastradh
159203b705cfSriastradh    kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d opcode = 0x%x\n", opcode);
159303b705cfSriastradh    return 1;
159403b705cfSriastradh}
159503b705cfSriastradh
159603b705cfSriastradh
159703b705cfSriastradhvoid kgem_gen3_finish_state(struct kgem *kgem)
159803b705cfSriastradh{
159903b705cfSriastradh	memset(&state, 0, sizeof(state));
160003b705cfSriastradh}
1601