;----------------------------------------------------------------------------
;File name:	SLC_COMP.S			Revision date:	1997.07.27
;C->S Port by:	Ulf Ronald Andersson		Port begun:	1996.08.02
;Original C by:	Dan Ackerman & Steve Adam
;----------------------------------------------------------------------------
;
	include	"uran\STRUCT.SH"
	include	"uran\URAn_SYS.SH"
	include	"stik\CSLIP_HD.SH"
	include	"stik\GLOBDEFS.SH"
;
;----------------------------------------------------------------------------
;	Macro definitions
;
;;; ENCODE encodes a number that is known to be non-zero.  ENCODEZ
;;; checks for zero (since zero has to be encoded in the long, 3 byte form).
;
;URAn NB: I have amended ENCODE to use the correct method and now use it alone
;
;
	.MACRO	ENCODE	dx
	.LOCAL	.do_code,.done_code
	movea.l	.cp(a6),a5
	tst	dx
	ble.s	.do_code	;if ((uint16)(n) == 0 || \
	cmpi	#256,dx
	blo.s	.done_code	;    (uint16)(n) >= 256) \
.do_code:
	clr.b	(a5)+		;{ *cp++ = 0; cp[1] = (n); cp[0] = (n) >> 8; cp += 2; } \
	ror	#8,dx		;swap hi byte with lo byte
	move.b	dx,(a5)+	;store hi byte
	ror	#8,dx		;swap hi byte with lo byte (restores orig value)
.done_code:
	move.b	dx,(a5)+	;else { *cp++ = (n); } \
	move.l	a5,.cp(a6)
	.ENDM			;}
;
;----------------------------------------------------------------------------
;
slc_comp:			;unsigned char slc_compress (b, comp, compress_cid)
;				;GPKT *b; struct slcompress *comp; long compress_cid; {
	XDEF	slc_comp	;extern unsigned char slc_compress (GPKT *b,	struct slcompress *comp, long compress_cid);
	lv_init	a6		;link local variables through a6
	movem.l	d3-d7/a2-a5,-(sp)	;protect entry registers for Pure_C
;Pure_C_def;	movea.l	8(a6),a0	;reg a0 is 'b'
;Pure_C_def;	movea.l	12(a6),a1	;reg a1 is 'comp'
;Pure_C_def;	move.l	16(a6),d0	;reg d0 is 'compress_cid'
;
;erase each ';Pure_C_def;' sequence above for CDECL function
;
	movea.l	slcm_last_cs(a1),a2
	movea.l	cs_next(a2),a2		;reg a2 is struct cstate *cs = comp->last_cs->cs_next;
;
	movea.l	gpkt_pip(a0),a3		;reg a3 is struct ip_header *ip = (struct ip_header *)b->pip;
;
	move.b	iph_ihl(a3),d1
	and.l	#mask_iph_ihl_bs,d1	;reg d1 is uint32 hlen = ip->ihl;
;---------------------------------------;reg a4 is TCP_HDR *oth;
;---------------------------------------;reg d2 is uint32 deltaS;
;---------------------------------------;reg d3 is uint32 deltaA;
	clr	d4			;reg d4 is int16 changes = 0;
;
;register variables above leave d5-d7/a5 free for calculations
;
	lvar.l	.th,1			;.th(a6) is TCP_HDR *th;
	lvar.b	.new_seq,16		;.new_seq(a6) is unsigned char new_seq[16];
	lvar.l	.cp,1			;.cp(a6) is unsigned char *cp;
;
	lea	.new_seq(a6),a5
	move.l	a5,.cp(a6)		;cp = new_seq;
;
;	/*
;	 * Bail if this is an IP fragment or if the TCP packet isn't
;	 * `compressible' (i.e., ACK isn't set or some other control bit is
;	 * set).  (We assume that the caller has already made sure the
;	 * packet is IP proto TCP). I fixed this it can be not TCP
;	 */
;	 
;	/* Bail if this packet isn't TCP, or is an IP fragment */
;
	cmpi.b	#IPPROTO_TCP,iph_ptcl(a3)
	bne.s	.ret_TYPE_IP			;if(ip->ptcl != IPPROTO_TCP
	move	iph_ofst(a3),d5
	bne.s	.ret_TYPE_IP			;|| ip->ofst != 0
;;;	andi	#~FLAG_DF,d5
;;;	bne.s	.ret_TYPE_IP			;|| ip->ofst & ~FLAG_DF
;The two lines above are redundant...!!!
	cmpi	#40,gpkt_ip_len(a0)
	bge.s	.non_TYPE_IP			;|| b->ip_len < 40)
.ret_TYPE_IP:
	moveq	#TYPE_IP,d0			;{ /* Send as regular IP */ return TYPE_IP; }
	bra	.exit
;
.non_TYPE_IP:
;	/* Extract TCP header */
	move.l	gpkt_mp(a0),.th(a6)		;th = (TCP_HDR *)b->mp;
;
;	/*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
;	 *  some other control bit is set).
;	 */
;
	movea.l	.th(a6),a5
	move.b	tcph_flags(a5),d5
	btst	#tcph_f_ack_bs,d5
	beq.s	.ret_TYPE_IP			;if( !th->f_ack
	andi	#(1<<tcph_f_syn_bs)|(1<<tcph_f_fin_bs)|(1<<tcph_f_rst_bs),d5
	bne.s	.ret_TYPE_IP			;    || th->f_syn || th->f_fin || th->f_rst )
;-----------------------------------------------;{ /* TCP connection stuff; send as regular IP */
;-----------------------------------------------;  return TYPE_IP; }
;
;	/*
;	 * Packet is compressible -- we're going to send either a
;	 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
;	 * to locate (or create) the connection state.  Special case the
;	 * most recently used connection since it's most likely to be used
;	 * again & we don't have to do any reordering if it's used.
;	 */
;	/*INCR (sls_packets);*/
;
	lea	cs_ip(a2),a5		;a5 = cs->cs_ip; -> ip_header of first cstate
	move.l	iph_s_ip(a5),d5
	cmp.l	iph_s_ip(a3),d5
	bne.s	.must_search		;if(ip->s_ip != cs->cs_ip.s_ip ||
	move.l	iph_d_ip(a5),d5
	cmp.l	iph_d_ip(a3),d5
	bne.s	.must_search		;   ip->d_ip != cs->cs_ip.d_ip ||
	move.b	iph_ihl(a5),d5
	and	#mask_iph_ihl_bs,d5
	asl	#2,d5			;NB: scaled for (long *)[]
	lea	(a5,d5),a5
	move.l	(a5),d5
	movea.l	.th(a6),a5
	cmp.l	(a5),d5
	beq.s	.done_search		;   *(long *)th != ((long *)&cs->cs_ip)[cs->cs_ip.ihl]) {
;
;		/*
;		 * Wasn't the first -- search for it.
;		 *
;		 * States are kept in a circularly linked list with
;		 * last_cs pointing to the end of the list.  The
;		 * list is kept in lru order by moving a state to the
;		 * head of the list whenever it is referenced.  Since
;		 * the list is short and, empirically, the connection
;		 * we want is almost always near the front, we locate
;		 * states via linear search.  If we don't find a state
;		 * for the datagram, the oldest state is (re-)used.
;		 */
;
.must_search:
	lvar.l	.lcs,1				;.lcs(a6) is struct cstate *lcs;
	lvar.l	.lastcs,1			;.lastcs(a6) is struct cstate *lastcs;
	move.l	slcm_last_cs(a1),.lastcs(a6)	;lastcs = comp->last_cs;
.search_loop:	;do {
	move.l	a2,.lcs(a6)	;lcs = cs;
	movea.l	cs_next(a2),a2	;cs = cs->cs_next;
;
	lea	cs_ip(a2),a5		;a5 = cs->cs_ip; -> ip_header of cstate to be tested
	move.l	iph_s_ip(a5),d5
	cmp.l	iph_s_ip(a3),d5
	bne.s	.not_found_yet		;if(ip->s_ip == cs->cs_ip.s_ip &&
	move.l	iph_d_ip(a5),d5
	cmp.l	iph_d_ip(a3),d5
	bne.s	.not_found_yet		;   ip->d_ip == cs->cs_ip.d_ip &&
	move.b	iph_ihl(a5),d5
	and	#mask_iph_ihl_bs,d5
	asl	#2,d5			;NB: scaled for (long *)[]
	lea	(a5,d5),a5
	move.l	(a5),d5
	movea.l	.th(a6),a5
	cmp.l	(a5),d5
	beq.s	.found_cstate		;   *(long *)th == ((long *)&cs->cs_ip)[cs->cs_ip.ihl]) { goto found; }
;
.not_found_yet:
	cmpa.l	.lastcs(a6),a2
	bne.s	.search_loop		;} while (cs != lastcs);
;
;		/*
;		 * Didn't find it -- re-use oldest cstate.  Send an
;		 * uncompressed packet that tells the other side what
;		 * connection number we're using for this conversation.
;		 * Note that since the state list is circular, the oldest
;		 * state points to the newest and we only need to set
;		 * last_cs to update the lru linkage.
;		 */
;
	move.l	.lcs(a6),slcm_last_cs(a1)	;comp->last_cs = lcs;
	move.l	.th(a6),a5
	move.b	tcph_ofst(a5),d5
	lsr.b	#tcph_ofst_bs,d5
	and.l	#mask_tcph_ofst_bs,d5		;d5 = th->ofst
	asl	#2,d5			;???	;d5 = th->ofst*4
	add.l	d5,d1				;hlen += th->ofst*4;
	asl	#2,d1				;hlen <<= 2;
	bra	.uncompressed			;goto uncompressed;

.found_cstate:
;
;		/*
;		 * Found it -- move to the front on the connection list.
;		 */
;
	cmpa.l	.lastcs(a6),a2
	bne.s	.not_last			;if (cs == lastcs)
	move.l	.lcs(a6),slcm_last_cs(a1)	;{ comp->last_cs = lcs;
	bra.s	.done_search			;}
;
.not_last:					;else {
	movea.l	.lcs(a6),a5
	move.l	cs_next(a2),cs_next(a5)		;lcs->cs_next = cs->cs_next;
	movea.l	.lastcs(a6),a5
	move.l	cs_next(a5),cs_next(a2)		;cs->cs_next = lastcs->cs_next;
	move.l	a2,cs_next(a5)			;lastcs->cs_next = cs; }}
.done_search:
;
;	/*
;	 * Make sure that only what we expect to change changed. The first
;	 * line of the `if' checks the IP protocol version, header length &
;	 * type of service.  The 2nd line checks the "Don't fragment" bit.
;	 * The 3rd line checks the time-to-live and protocol (the protocol
;	 * check is unnecessary but costless).  The 4th line checks the TCP
;	 * header length.  The 5th line checks IP options, if any.  The 6th
;	 * line checks TCP options, if any.  If any of these things are
;	 * different between the previous & current datagram, we send the
;	 * current datagram `uncompressed'.
;	 */
;
	lea	cs_ip(a2),a5		;a5 = cs->cs_ip; -> ip_header of cstate to be tested
	move.l	d1,d5			;d5 = hlen
	asl.l	#2,d5			;d5 *= 4  to be scaled for long indexing
	lea	(a5,d5.l),a4		;oth = (TCP_HDR *)&((long *)&cs->cs_ip)[hlen];
	move.l	d1,d2			;deltaS = hlen;
	move.l	.th(a6),a5
	move.b	tcph_ofst(a5),d6
	lsr.b	#tcph_ofst_bs,d6
	and.l	#mask_tcph_ofst_bs,d6		;d6 = th->ofst
	asl	#2,d6			;???	;d6 = th->ofst*4   NB: kept in d6 for tests below
	add.l	d6,d1				;hlen += th->ofst*4;
	asl	#2,d1				;hlen <<= 2;
;
	lea	cs_ip(a2),a5		;a5 = cs->cs_ip; -> ip_header of cstate to be tested
	move	(a5),d5
	cmp	(a3),d5			;compare iph_ver, iph_ihl, iph_tos in one opcode
	bne	.uncompressed		;if (((unsigned short *)ip)[0] != ((unsigned short *)&cs->cs_ip)[0] ||
	move	iph_ofst(a5),d5
	cmp	iph_ofst(a3),d5		;compare iph_ofst incl flags
	bne	.uncompressed		;    ((unsigned short *)ip)[3] != ((unsigned short *)&cs->cs_ip)[3] ||
	move	iph_ttl(a5),d5
	cmp	iph_ttl(a3),d5		;compare iph_ttl, iph_ptcl in one opcode
	bne	.uncompressed		;    ((unsigned short *)ip)[4] != ((unsigned short *)&cs->cs_ip)[4] ||
	move.b	tcph_ofst(a4),d5
	lsr.b	#tcph_ofst_bs,d5
	and	#mask_tcph_ofst_bs,d5	;d5 = oth->ofst
	asl	#2,d5		;???	;d5 = oth->ofst*4   NB: d6 still has th->ofst*4
	cmp	d5,d6
	bne	.uncompressed		;    th->ofst*4 != oth->ofst*4 ||
	cmpi	#5,d2
	bls.s	.done_IP_options	;    (deltaS > 5 &&
	move	d2,d5
	subq	#5,d5
	asl	#2,d5			;d5 = comparison byte count
	addq	#1,a5			;a5 = &cs->cs_ip + 1
	move.l	a3,d7			;save ip in d7
	addq	#1,a3			;a3 = ip + 1
	subq	#1,d5			;d5 = dbra count
.cmp_IP_opts:				;     BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
	cmpm.b	(a3)+,(a5)+
	dbne	d5,.cmp_IP_opts
	movea.l	d7,a3			;restore ip, without affecting CPU flags
	bne	.uncompressed
.done_IP_options:
	cmpi	#5,d6
	bls.s	.done_TCP_options	;    (th->ofst*4 > 5 &&
	subq	#5,d6
	asl	#2,d6			;d6 = comparison byte count
	movea.l	.th(a6),a5
	addq	#1,a5			;a5 = th + 1
	move.l	a4,d7			;save oth in d7
	addq	#1,a4			;a4 = oth + 1
	subq	#1,d6			;d6 = dbra count
.cmp_TCP_opts:				;     BCMP(th + 1, oth + 1, (th->ofst*4 - 5) << 2))) goto uncompressed;
	cmpm.b	(a4)+,(a5)+
	dbne	d5,.cmp_TCP_opts
	movea.l	d7,a4			;restore oth, without affecting CPU flags
	bne	.uncompressed
.done_TCP_options:
;
;	/*
;	 * Figure out which of the changing fields changed.  The
;	 * receiver expects changes in the order: urgent, window,
;	 * ack, seq (the order minimizes the number of temporaries
;	 * needed in this section of code).
;	 */
;
	movea.l	.th(a6),a5		;a5 = th
	move.b	tcph_f_urg(a5),d5
	btst	#tcph_f_urg_bs,d5
	beq.s	no_f_urg		;if (th->f_urg) {
	clr.l	d2
	move	tcph_urgent(a5),d2	;  deltaS = th->urgent;
	ENCODE	d2			;  ENCODE(deltaS); /* was ENCODEZ */
	ori	#NEW_U,d4		;  changes |= NEW_U; }
	bra.s	done_f_urg
;
no_f_urg:				;else
	move	tcph_urgent(a5),d5
	cmp	tcph_urgent(a4),d5
	bne	.uncompressed		;if (th->urgent != oth->urgent) goto uncompressed;
;					/* argh! URG not set but urp changed -- a sensible
;					 * implementation should never do this but RFC793
;					 * doesn't prohibit the change so we have to deal
;					 * with it. */
done_f_urg:
	movea.l	.th(a6),a5		;a5 = th
	move	tcph_window(a5),d2
	sub	tcph_window(a4),d2	;deltaS = th->window - oth->window;
	beq.s	done_window		;if (deltaS != 0) {
	ENCODE	d2			;  ENCODE(deltaS);
	ori	#NEW_W,d4		;  changes |= NEW_W; }
done_window:
	movea.l	.th(a6),a5		;a5 = th
	move.l	tcph_ack(a5),d3
	sub.l	tcph_ack(a4),d3		;deltaA = th->ack - oth->ack;
	beq.s	done_ack		;if (deltaA != 0L) {
	cmp.l	#$FFFF,d3
	bhi	.uncompressed		;  if (deltaA > 0x0000ffff) goto uncompressed;
	ENCODE	d3			;  ENCODE(deltaA);
	ori	#NEW_A,d4		;  changes |= NEW_A; }
done_ack:
	movea.l	.th(a6),a5		;a5 = th
	move.l	tcph_seq(a5),d2
	sub.l	tcph_seq(a4),d2		;deltaS = th->seq - oth->seq;
	beq.s	done_seq		;if (deltaS != 0L) {
	cmp.l	#$FFFF,d2
	bhi	.uncompressed		;  if (deltaS > 0x0000ffff) goto uncompressed;
	ENCODE	d2			;  ENCODE(deltaS);
	ori	#NEW_S,d4		;  changes |= NEW_S; }
done_seq:
;
;	/*printf("After encoding\r\n");*/
;
;			switch(changes) {
;
	tst	d4
	bne.s	.past_case_0		;case 0:
;
;		/*
;		 * Nothing changed. If this packet contains data and the
;		 * last one didn't, this is probably a data packet following
;		 * an ack (normal on an interactive connection) and we send
;		 * it compressed.  Otherwise it's probably a retransmit,
;		 * retransmitted ack or window probe.  Send it uncompressed
;		 * in case the other side missed the compressed version.
;		 */
;
	move	cs_ip+iph_len(a2),d5
	cmp	iph_len(a3),d5
	beq	.uncompressed			;if(ip->len != cs->cs_ip.len &&
	cmp	d1,d5
	beq.s	.break_switch			;   cs->cs_ip.len == hlen) break;
	bra	.uncompressed			;  goto uncompressed;
;
;
.past_case_0:
	cmp	#SPECIAL_I,d4
	beq.s	.case_SPECIAL		;case SPECIAL_I:
	cmp	#SPECIAL_D,d4
	bne.s	.past_case_SPECIAL		;case SPECIAL_D:
.case_SPECIAL:
;
;		/*
;		 * actual changes match one of our special case encodings --
;		 * send packet uncompressed.
;		 */
;
	bra	.uncompressed			;goto uncompressed;
;
;
.past_case_SPECIAL:
	cmp	#NEW_S|NEW_A,d4
	bne.s	.past_case_NEW_S_NEW_A	;case NEW_S|NEW_A:
	cmp.l	d2,d3
	bne.s	.break_switch			;if (deltaS == deltaA &&
	clr.l	d5
	move	cs_ip+iph_len(a2),d5
	sub.l	d1,d5
	cmp.l	d2,d5
	bne.s	.break_switch			;    deltaS == cs->cs_ip.len - hlen) {
;
;	/* special case for echoed terminal traffic */
;
	moveq	#SPECIAL_I,d4			;  changes = SPECIAL_I;
	lea	.new_seq(a6),a5
	move.l	a5,.cp(a6)			;  cp = new_seq; }
	bra.s	.break_switch			;break;
;
;
.past_case_NEW_S_NEW_A:
	cmp	#NEW_S,d4
	bne.s	.past_NEW_S		;case NEW_S:
	clr.l	d5
	move	cs_ip+iph_len(a2),d5
	sub.l	d1,d5
	cmp.l	d2,d5
	bne.s	.break_switch			;if (deltaS == cs->cs_ip.len - hlen) {
;
;	/* special case for data xfer */
;
	moveq	#SPECIAL_D,d4			;  changes = SPECIAL_D;
	lea	.new_seq(a6),a5
	move.l	a5,.cp(a6)			;  cp = new_seq; }
	bra	.break_switch			;break;
.past_NEW_S:
.break_switch:				;}
;
	clr.l	d5
	move	iph_id(a3),d5
	sub	iph_id+cs_ip(a2),d5
	move.l	d5,d2			;deltaS = ip->id - cs->cs_ip.id;
	cmp.l	#1,d2
	beq.s	done_NEW_I		;if (deltaS != 1) {
	ENCODE	d2			;  ENCODE(deltaS);
	ori	#NEW_I,d4		;  changes |= NEW_I; }
done_NEW_I:
	movea.l	.th(a6),a5		;a5 = th
	move.b	tcph_f_psh(a5),d5
	btst	#tcph_f_psh_bs,d5
	beq.s	.no_f_psh		;if (th->f_psh)
	ori	#TCP_PUSH_BIT,d4	;  changes |= TCP_PUSH_BIT;
.no_f_psh:
;
;	/*
;	 * Grab the cksum before we overwrite it below.  Then update our
;	 * state with this packet's header.
;	 */
;
	movea.l	.th(a6),a5		;a5 = th
	clr.l	d3
	move	tcph_sum(a5),d3		;deltaA = th->sum;
;
	move	d1,d5			;d5 = byte count
	beq.s	.done_cpy_1
	subq	#1,d5			;d5 = dbra count
	lea	cs_ip(a2),a5		;a5 = &cs->cs_ip
	move.l	a3,d7			;save ip in d7
.copy_loop_1:				;BCOPY(ip, &cs->cs_ip, hlen);
	move.b	(a3)+,(a5)+
	dbra	d5,.copy_loop_1
	movea.l	d7,a3			;restore ip
.done_cpy_1:
;
;	/*
;	 * We want to use the original packet as our compressed packet.
;	 * (cp - new_seq) is the number of bytes we need for compressed
;	 * sequence numbers.  In addition we need one byte for the change
;	 * mask, one for the connection id and two for the tcp checksum.
;	 * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
;	 * many bytes of the original packet to toss so subtract the two to
;	 * get the new packet size.
;	 */
;
	move.l	.cp(a6),d2
	lea	.new_seq(a6),a5
	sub.l	a5,d2			;deltaS = cp - new_seq;
	move.l	a3,.cp(a6)		;cp = (unsigned char *)ip;
	tst.l	d0
	beq.s	.xxx_1			;if (compress_cid == 0 ||
	move.b	cs_id(a2),d5
	cmp.b	slcm_last_xmit(a1),d5
	beq.s	.xxx_2			;    comp->last_xmit != cs->cs_id) {
.xxx_1:
	move.b	d5,slcm_last_xmit(a1)	;  comp->last_xmit = cs->cs_id;
	sub.l	d2,d1
	subq.l	#4,d1			;  hlen -= deltaS + 4;
	add.l	d1,.cp(a6)		;  cp += hlen;
	move	d4,d5
	ori	#NEW_C,d5
	movea.l	.cp(a6),a5
	move.b	d5,(a5)+		;  *cp++ = changes | NEW_C;
	move.b	cs_id(a2),(a5)+		;  *cp++ = cs->cs_id;
	move.l	a5,.cp(a6)
	bra.s	.xxx_3			;}
;					;else {
.xxx_2:
	sub.l	d2,d1
	subq.l	#3,d1			;  hlen -= deltaS + 3;
	add.l	d1,.cp(a6)		;  cp += hlen;
	movea.l	.cp(a6),a5
	move.b	d4,(a5)+		;  *cp++ = changes;
	move.l	a5,.cp(a6)		;}
.xxx_3:
	add.l	d1,gpkt_fp(a0)		;b->fp += hlen;
	movea.l	.cp(a6),a5
	ror	#8,d3
	move.b	d3,(a5)+		;*cp++ = deltaA >> 8;
	ror	#8,d3
	move.b	d3,(a5)+		;*cp++ = deltaA;
	move.l	a5,.cp(a6)
	lea	.new_seq(a6),a3
	move	d2,d5			;d5 = byte count
	beq.s	.done_cpy_2
	subq	#1,d5			;d5 = dbra count
.copy_loop_2:				;BCOPY(new_seq, cp, deltaS);
	move.b	(a3)+,(a5)+
	dbra	d5,.copy_loop_1
.done_cpy_2:
	move.l	#TYPE_COMPRESSED_TCP,d0
	bra.s	.exit			;return (TYPE_COMPRESSED_TCP);
;
;
;	/*
;	 * Update connection state cs & send uncompressed packet ('uncompressed'
;	 * means a regular ip/tcp packet but with the 'conversation id' we hope
;	 * to use on future compressed packets in the protocol field).
;	 */
;
.uncompressed:					;uncompressed:
;
	move	d1,d5			;d5 = byte count
	beq.s	.done_cpy_3
	subq	#1,d5			;d5 = dbra count
	lea	cs_ip(a2),a5		;a5 = &cs->cs_ip
	move.l	a3,d7			;save ip in d7
.copy_loop_3:				;BCOPY(ip, &cs->cs_ip, hlen);
	move.b	(a3)+,(a5)+
	dbra	d5,.copy_loop_3
	movea.l	d7,a3			;restore ip
.done_cpy_3:
;
	move.b	cs_id(a2),iph_ptcl(a3)		;ip->ptcl = cs->cs_id;
	move.b	cs_id(a2),slcm_last_xmit(a1)	;comp->last_xmit = cs->cs_id;
	moveq	#TYPE_UNCOMPRESSED_TCP,d0	;return (TYPE_UNCOMPRESSED_TCP); }
.exit:
	movem.l	(sp)+,d3-d7/a2-a5	;restore entry registers for Pure_C
	lv_exit	a6			;unlink local variables through a6
	rts
;
;----------------------------------------------------------------------------
VJ_enco:			;void VJ_enco(cpp, data)
;				;void **cpp; uint16 data;
	XDEF	VJ_enco		;extern void VJ_enco(void **cpp, uint16 data)
;Pure_C_def;	movea.l	4(sp),a0	;reg a0 is 'cpp'
;Pure_C_def;	movea.l	8(sp),d0	;reg d0 is 'data'
;
;erase each ';Pure_C_def;' sequence above for CDECL function
;
	move.l	(a0),a1		;a1 -> pack destination
	tst	d0
	ble.s	.pack_3
	cmpi	#256,d0
	blo.s	.pack_1
.pack_3:
	clr.b	(a1)+
	ror	#8,d0
	move.b	d0,(a1)+
	ror	#8,d0
.pack_1:
	move.b	d0,(a1)+
	move.l	a1,(a0)		;store the updated pointer
	rts
;
;----------------------------------------------------------------------------
;End of file:	SLC_COMP.S
;----------------------------------------------------------------------------
