	AREA	|C$$CODE|, CODE, READONLY

	EXPORT	oggpack_readinit
	EXPORT	oggpack_look
	EXPORT	oggpack_look1
	EXPORT	oggpack_adv
	EXPORT	oggpack_adv1
	EXPORT	oggpack_read
	EXPORT	oggpack_read1

	; oggpack_buffer
	; {
	;    uint32_t *p;
	;    uint32_t  bits;
	;    uint32_t *p_end;
	;    uint32_t  bits_end
	; }

oggpack_readinit
	; r0 = oggpack_buffer *b;
	; r1 = uint8_t        *buffer
	; r2 = uint32_t        len;
	BIC	r3,r1,#3	; r3 = p
	AND	r12,r1,#3
	MOV	r12,r12,LSL#3	; r12 = bits
	RSB	r12,r12,#32	; r12 = bits left
	STMIA	r0!,{r3,r12}
	ADD	r1,r1,r2
	BIC	r3,r1,#3	; r3 = p
	AND	r12,r1,#3
	MOV	r12,r12,LSL#3	; r12 = bits
	RSB	r12,r12,#32	; r12 = bits left
	STMIA	r0!,{r3,r12}

	MOV	PC,R14

oggpack_look
	; r0 = oggpack_buffer *b
	; r1 = uint32_t        bits
	STMFD	r13!,{r4-r6,r14}

	LDMIA	r0,{r2,r3,r12,r14}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	LDMIA	r2,{r4,r5}
	RSB	r6,r3,#32
	MOV	r4,r4,LSR r6
	MOV	r6,#1
	ORR	r4,r4,r5,LSL r3
	SUBS	r3,r3,r1
	RSB	r6,r6,r6,LSL r1		; r6 = mask

	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	CMP	r2,r12		; HI => overrun
	CMPEQ	r14,r3		; EQ => check bits, GE => overrun
	;STMIA	r0,{r2,r3}
	MVNHI	r0,#0
	ANDLS	r0,r4,r6		; r4 = return value

	LDMFD	r13!,{r4-r6,PC}

oggpack_look1
	; r0 = oggpack_buffer *b
	STR	r14,[r13,#-4]!

	LDMIA	r0,{r2,r3,r12,r14}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	LDR	r1,[r2]
	RSB	R3,R3,#32
	MOV	r1,r1,LSR r3

	RSBS	r3,r3,#31
	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	CMP	r2,r12		; HI => overrun
	CMPEQ	r14,r3		; EQ => check bits, GE => overrun
	;STMIA	r0,{r2,r3}
	MVNHI	r0,#0
	ANDLS	r0,r1,#1		; r4 = return value

	LDR	PC,[r13],#4

oggpack_adv
	; r0 = oggpack_buffer *b
	; r1 = uint32_t        bits
	LDMIA	r0,{r2,r3}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	SUBS	r3,r3,r1
	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	STMIA	r0,{r2,r3}
	MOV	PC,R14

oggpack_adv1
	; r0 = oggpack_buffer *b
	LDMIA	r0,{r2,r3}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	SUBS	r3,r3,#1
	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	STMIA	r0,{r2,r3}
	MOV	PC,R14

oggpack_read
	; r0 = oggpack_buffer *b
	; r1 = uint32_t        bits
	STMFD	r13!,{r4-r6,r14}

	LDMIA	r0,{r2,r3,r12,r14}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	LDMIA	r2,{r4,r5}
	RSB	r6,r3,#32
	MOV	r4,r4,LSR r6
	MOV	r6,#1
	ORR	r4,r4,r5,LSL r3
	SUBS	r3,r3,r1
	RSB	r6,r6,r6,LSL r1		; r6 = mask

	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	CMP	r2,r12		; HI => overrun
	CMPEQ	r14,r3		; EQ => check bits, GE => overrun
	STMIA	r0,{r2,r3}
	MVNHI	r0,#0
	ANDLS	r0,r4,r6		; r4 = return value

	LDMFD	r13!,{r4-r6,PC}

oggpack_read1
	; r0 = oggpack_buffer *b
	STR	r14,[r13,#-4]!

	LDMIA	r0,{r2,r3,r12,r14}	; r2 = p
					; r3 = bitsleft
					; r12= p_end
					; r14= bitsleft_end
	LDR	r1,[r2]
	RSB	R3,R3,#32
	MOV	r1,r1,LSR r3
	RSBS	r3,r3,#31
	ADDLE	r3,r3,#32
	ADDLE	r2,r2,#4

	CMP	r2,r12		; HI => overrun
	CMPEQ	r14,r3		; EQ => check bits, GE => overrun
	STMIA	r0,{r2,r3}
	MVNHI	r0,#0
	ANDLS	r0,r1,#1		; r4 = return value

	LDR	PC,[r13],#4

	END
