/* parseblock.c */

#include "mphead.h"

extern inline void
memset4(s,c,count)
char *s;
{
__asm__("cld\n\t"
	"rep\n\t"
	"stosl"
	: /* no output */
	:"a" (c),"D" (s),"c" (count)
	:"cx","di","memory");
}

extern unsigned char dct_dc_size_luminance[128];
extern unsigned char dct_dc_size_chrominance[256];
extern unsigned short dct_coeff_tbl_0[256];
extern unsigned short dct_coeff_tbl_1[16];
extern unsigned short dct_coeff_tbl_2_3[2][4];
extern unsigned short dct_coeff_next[256];
extern unsigned short dct_coeff_first[256];

extern unsigned char zigzag[64];
extern int scaled_intra_quant_matrix[64],scaled_non_intra_quant_matrix[64];
extern short block[64];
extern dc_cb_past,dc_cr_past,dc_y_past;
extern pict_type;
extern intra,mb_address,past_intra_addr;

static inline int
decode_dct_coeff(dct_coeff_tbl,level)
unsigned short *dct_coeff_tbl;
int *level;
{
	int i,j;

	fill_bitsn(9);
	i = show_bitsn(8);
	if (i > 3) {
		i = dct_coeff_tbl[i];
		if ((j=i>>RUN_SHIFT) == END_OF_BLOCK)
			return END_OF_BLOCK;
		flush_bitsn((i&NUM_MASK)+1);
		if (j != ESCAPE) {
			i = i>>LEVEL_SHIFT & LEVEL_MASK;
			*level = get_bitsn(1) ? -i : i;
			return j;
		}
		fill_bitsn(22);
		i = get_bitsn(14);
		j = i>>8;
		i &= 255;
		if (i == 0) {
			*level = get_bitsn(8);
			return j;
		}
		if (i != 128) {
			*level = (signed char)i;
			return j;
		}
		*level = get_bitsn(8)-256;
		return j;
	}
	if (i > 1) {
		fill_bitsn(11);
		i = dct_coeff_tbl_2_3[i-2][show_bitsn(10)&3];
	}
	else if (i) {
		fill_bitsn(13);
		i = dct_coeff_tbl_1[show_bitsn(12)&15];
	}
	else {
		fill_bitsn(17);
		i = dct_coeff_tbl_0[show_bitsn(16)&255];
	}
	flush_bitsn((i&NUM_MASK)+1);
	j = i>>LEVEL_SHIFT & LEVEL_MASK;
	*level = get_bitsn(1) ? -j : j;
	return i >> RUN_SHIFT;
}

parse_recon_block(n)
{
	int i,j,l,z = 1;
	int *q;

	memset4(block,0,32);
	if (intra) {
		if (n < 4) {
			fill_bitsn(15);
			i = dct_dc_size_luminance[show_bitsn(7)];
			flush_bitsn(i&15);
			i >>= 4;
			j = 0;
			if (i) {
				j = get_bitsn(i);
				if (!(j&1<<i-1))
					j = 0xffffffff<<i | j+1;
				j *= 8;
			}
			i = j + dc_y_past;
			if (n==0 && mb_address-past_intra_addr>1)
				i = j + 1024;
			dc_y_past = i;
		}
		else {
			fill_bitsn(16);
			i = dct_dc_size_chrominance[show_bitsn(8)];
			flush_bitsn(i&15);
			i >>= 4;
			j = 0;
			if (i) {
				j = get_bitsn(i);
				if (!(j&1<<i-1))
					j = 0xffffffff<<i | j+1;
				j *= 8;
			}
			if (n == 4) {
				i = j + dc_cr_past;
				if (mb_address-past_intra_addr > 1)
					i = j + 1024;
				dc_cr_past = i;
			}
			else {
				i = j + dc_cb_past;
				if (mb_address-past_intra_addr > 1)
					i = j + 1024;
				dc_cb_past = i;
			}
		}
		block[0] = i;
		i = 0;
		q = scaled_intra_quant_matrix;
	}
	else {
		q = scaled_non_intra_quant_matrix;
		i = decode_dct_coeff(dct_coeff_first,&l);
		block[zigzag[i]] = l*q[i] >> 3;
	}
	if (pict_type != 4) {
		if ((j=decode_dct_coeff(dct_coeff_next,&l)) != END_OF_BLOCK) {
			do {
				i += j+1;
				block[zigzag[i]] = l*q[i] >> 3;
			} while ((j=decode_dct_coeff(dct_coeff_next,&l)) != END_OF_BLOCK);
			z = 0;
		}
		fill_bitsn(2);
		flush_bitsn(2);
	}
	asm_rev_dct(z,block);
}

skip_block(n)
{
	int i,l;

	if (intra) {
		if (n < 4) {
			fill_bitsn(15);
			i = dct_dc_size_luminance[show_bitsn(7)];
			flush_bitsn((i&15) + (i>>4));
		}
		else {
			fill_bitsn(16);
			i = dct_dc_size_chrominance[show_bitsn(8)];
			flush_bitsn((i&15) + (i>>4));
		}
	}
	else
		decode_dct_coeff(dct_coeff_first,&l);
	if (pict_type != 4) {
		while (decode_dct_coeff(dct_coeff_next,&l) != END_OF_BLOCK)
			;
		fill_bitsn(2);
		flush_bitsn(2);
	}
}
