/********************************************************************************
 *																				*	
 *  getbits.c, bit level routines for tmndecode (H.263 decoder)					*
 *  Copyright (C) 1995, 1996  Telenor R&D, Norway								*
 *																				*
 *  Contacts:																	*	
 *  Robert Danielsen                  <Robert.Danielsen@nta.no>					*
 *																				*
 *  Telenor Research and Development  http://www.nta.no/brukere/DVC/			*
 *  P.O.Box 83                        tel.:   +47 63 84 84 00					*	
 *  N-2007 Kjeller, Norway            fax.:   +47 63 81 00 76					*
 *																				*
 *  Copyright (C) 1997  University of BC, Canada								*
 *  Modified by: Michael Gallant <mikeg@ee.ubc.ca>								*
 *               Guy Cote <guyc@ee.ubc.ca>										*
 *               Berna Erol <bernae@ee.ubc.ca>									*		
 *																				*
 *  Contacts:																	*
 *  Michael Gallant                   <mikeg@ee.ubc.ca>							*
 *																				*
 *  UBC Image Processing Laboratory   http://www.ee.ubc.ca/image				*
 *  2356 Main Mall                    tel.: +1 604 822 4051						*
 *  Vancouver BC Canada V6T1Z4        fax.: +1 604 822 5949						*
 *																				*				
 ********************************************************************************
 *																				*
 * This code has been developed by Project Mayo. This software is an			*
 * implementation of a part of one or more MPEG-4 Video tools as				*
 * specified in ISO/IEC 14496-2 standard.  Those intending to use this			*
 * software module in hardware or software products are advised that its		*
 * use may infringe existing patents or copyrights, and any such use			*
 * would be at such party's own risk.  The original developer of this			*
 * software module and his/her company, and subsequent editors and their		*
 * companies (including Project Mayo), will have no liability for use of		*
 * this software or modifications or derivatives thereof.						*
 *																				*
 ********************************************************************************
 *																				*	
 * This program is free software; you can redistribute it and/or modify			*
 * it under the terms of the GNU General Public License as published by			*
 * the Free Software Foundation; either version 2 of the License, or			*
 * (at your option) any later version.											*
 *																				*
 * The GPL can be found at: http://www.gnu.org/copyleft/gpl.html				*
 *																				*
 * Authors:																		*
 *																				*
 *	Andrea Graziani	(Ag):														*
 *		- Code Adaptation (Open Divx Decoder 0.4a).								*		
 *																				*
 *	Pedro Mateu		(Pm):														*
 *		- Heavily modified and optimized code + MIPS ASM.						*
 *																				*
 ********************************************************************************/

#include "global.h"

#define _SWAP(a) ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]) 

void initbits (unsigned char *stream)
{
	ld.bitcnt = 0;
	ld.rdptr = stream;
}

#ifndef MIPS_ASM

void flushbits (int n) 
{ 
	ld.bitcnt += n; 
	if (ld.bitcnt >= 8) { 
		ld.rdptr += ld.bitcnt >> 3; 
		ld.bitcnt = (ld.bitcnt&(0x7));// % 8;	
	}
} 

unsigned int showbits (int n) 
{ 
	return ((_SWAP(ld.rdptr))>>(32-ld.bitcnt-n))&(0xFFFFFFFF>>(32-n)); 
} 

unsigned int getbits (int n) 
{ 

	unsigned int l;
	l=((_SWAP(ld.rdptr))>>(32-ld.bitcnt-n))&(0xFFFFFFFF>>(32-n));
	ld.bitcnt += n; 
	if (ld.bitcnt >= 8) { 
		ld.rdptr += (ld.bitcnt)>>3; 
		ld.bitcnt = ld.bitcnt &(0x7); 
	}
	return l;

} 

unsigned int getbits1() 
{ 
	int l;
	l=((ld.rdptr[0])>>(7-ld.bitcnt))&0x001;
	ld.bitcnt += 1; 
	if (ld.bitcnt >= 8) { 
		ld.rdptr += (ld.bitcnt)>>3; 
		ld.bitcnt = ld.bitcnt &(0x7); 
	} 
	return l; 
} 

#else

void flushbits (int n) 
{ 
__asm(  ".globl ld;"
		"la		$8,ld;"
		"lw		$9,0($8);"
		"addu	$9,$9,$4;"
		"slti	$25,$9,8;"
		"bne	$25,$0,final_flushbits;"
		"lw		$10,4($8);"
		"sra	$11,$9,3;"
		"andi	$9,$9,0x7;"
		"addu	$10,$10,$11;"
		"sw		$10,4($8);"
		"final_flushbits:sw		$9,0($8);");
} 

unsigned int showbits (int n) 
{ 
__asm(  ".globl ld;"
		"la		$8,ld;"
		"lw		$9,0($8);"//ld.bitcnt
		"lw		$10,4($8);"//ld.rdptr
		
		"li 	$25,32;" //32-ld-n...
		"sub	$25,$25,$4;"
		"sub	$15,$25,$9;"

		"lbu	$11,0($10);"//swap
		"lbu	$12,1($10);"
		"lbu	$13,2($10);"
		"lbu	$14,3($10);"
		"sll	$13,$13,8;"
		"or		$14,$14,$13;"
		"sll	$12,$12,16;"
		"or		$14,$14,$12;"
		"sll	$11,$11,24;"
		"or		$14,$14,$11;"
	
		"srlv	$14,$14,$15;" //swap>>
		
		"li		$24,-1;"
		"srlv	$24,$24,$25;"
		
		//resultado

		"and	$2,$14,$24;");
} 

unsigned int getbits (int n) 
{ 
__asm(  ".globl ld;"
		"la		$8,ld;"
		"lw		$9,0($8);"//ld.bitcnt
		"lw		$10,4($8);"//ld.rdptr
		
		"li 	$25,32;" //32-ld-n...
		"sub	$25,$25,$4;"
		"sub	$15,$25,$9;"

		"lbu	$11,0($10);"//swap
		"lbu	$12,1($10);"
		"lbu	$13,2($10);"
		"lbu	$14,3($10);"
		"sll	$13,$13,8;"
		"or		$14,$14,$13;"
		"sll	$12,$12,16;"
		"or		$14,$14,$12;"
		"sll	$11,$11,24;"
		"or		$14,$14,$11;"
	
		"srlv	$14,$14,$15;" //swap>>
		
		"li		$24,-1;"
		"srlv	$24,$24,$25;"
		
		//resultado

		"and	$2,$14,$24;"
		
		"addu	$9,$9,$4;"
		"slti	$25,$9,8;"
		"bne	$25,$0,final_getbits;"
		"sra	$11,$9,3;"
		"andi	$9,$9,0x7;"
		"addu	$10,$10,$11;"
		"sw		$10,4($8);"
		"final_getbits:sw		$9,0($8);");

} 

unsigned int getbits1() 
{ 
__asm(  ".globl ld;"
		"la		$8,ld;"
		"lw		$9,0($8);"//ld.bitcnt
		"lw		$10,4($8);"//ld.rdptr
		
		"li 	$25,7;" //7-ld-n...
		"sub	$15,$25,$9;"

		"lbu	$11,0($10);"//swap
	
		"srlv	$11,$11,$15;" //swap>>
		
		"li		$24,1;"
		
		//resultado

		"and	$2,$11,$24;"
		
		"addi	$9,$9,1;"
		"slti	$25,$9,8;"
		"bne	$25,$0,final_getbits1;"
		"sra	$11,$9,3;"
		"andi	$9,$9,0x7;"
		"addu	$10,$10,$11;"
		"sw		$10,4($8);"
		"final_getbits1:sw		$9,0($8);");
} 

#endif