// Math32.c
// Multi-bit math
// Written for PCM C compiler by Custom Computer Services
// Tab size = 2
// Copyright 1995-2004 by Canzona Technologies

#ifndef __MATH32_C
	#define __MATH32_C

/***********************************************************************
	#define StackDataSize as size of stack parameters in bytes
	MathPtr must be externally initialized to lowest address of stack
	xxxPtr() parameters passed in MathSrcP, MathDstP, result in MathDstP
	xxxStk() parameters removed from stack, result left on stack
	MulPtr(), DivPtr() use scratch register

	NegPtr() uses 2 stack levels including call
	MulPtr(), DivPtr(), SLPtr(), SRPtr()  use 2 stack levels including call
	MulsPtr(), DivsPtr(), use 3 stack levels including call
	Other xxxPtr() functions use 1 stack level including call
	xxxStk() functions use 1 stack level + xxxPtr() stack requirements
	No error checking for stack
************************************************************************/

// Numeric parameter size in bytes
#ifndef StackDataSize
	#define StackDataSize 4
#endif

// Carry status for shifts, add/sub result
// Carry set for overflow (ADDWF result), or no underflow (SUBWF result)
bit		MathCarry;

// Double precision products and dividends if set
#ifdef dMathDouble
	bit		MathDouble = 0;
#endif

// Math stack
byte *MathPtr;
byte *MathDstP;								// xxxPtr() destination pointer
byte *MathSrcP;								// xxxPtr() source pointer

#ifndef dMathTPtr
	#define dMathTPtr MathPtr
#endif

// Next stack address is scratch register for intermediate calculations
#byte		MulTPtr = dMathTPtr		// Multiplication scratch register
#byte		DivTPtr = dMathTPtr		// Division scratch register

#inline
// Save carry in MathCarry
void	SaveCarry()
{
	MathCarry = 0;						// Assume no carry
	if (status_c) MathCarry = 1;
}

#inline
// Restore carry from MathCarry
void RestoreCarry()
{
	status_c = 0;
	if (MathCarry) status_c = 1;
}

void PushStk(byte *ptr)
{
	byte	MathCnt;						// Byte count for calculations
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		*MathPtr++ = *ptr++;
	}
}

void PushStk32(byte b1, byte b2, byte b3, byte b4)
{
	*MathPtr++  = b1;
	*MathPtr++  = b2;
	*MathPtr++  = b3;
	*MathPtr++  = b4;
}
#define dPushStk32(v32) PushStk32(v32, (v32)>>8, (v32)>>16, (v32)>>24);

// Push unsigned 16-bit value
void PushStk16(byte low, byte hi)
{
	byte	MathCnt;						// Byte count for calculations
	*MathPtr++  = low;
	*MathPtr++  = hi;
	#if StackDataSize > 2
		for (MathCnt = StackDataSize-2; MathCnt != 0; MathCnt--)
		{
			*MathPtr++ = 0;
		}
	#endif
}

// Push unsigned long
void PushStkLong(long val)
{
	byte	MathCnt;						// Byte count for calculations
	*MathPtr++ = val & 0xff;
	*MathPtr++ = val >> 8;
	#if StackDataSize > 2
		for (MathCnt = StackDataSize-2; MathCnt != 0; MathCnt--)
		{
			*MathPtr++ = 0;
		}
	#endif
}

// Push signed 8-bit value
void PushStkS8(byte val)
{
	byte	MathCnt;						// Byte count for calculations
	byte	temp;
	*MathPtr++  = val;
	#if StackDataSize > 1
		temp = 0;
		if (BIT_TEST(val, 7)) temp--;
		for (MathCnt = StackDataSize-1; MathCnt != 0; MathCnt--)
		{
			*MathPtr++ = temp;
		}
	#endif
}

// Push signed 16-bit value
void PushStkS16(byte low, byte hi)
{
	byte	MathCnt;						// Byte count for calculations
	byte	temp;
	*MathPtr++  = low;
	*MathPtr++  = hi;
	#if StackDataSize > 2
		temp = 0;
		if (BIT_TEST(hi, 7)) temp--;
		for (MathCnt = StackDataSize-2; MathCnt != 0; MathCnt--)
		{
			*MathPtr++ = temp;
		}
	#endif
}

// Push signed long
void PushStkSlong(long val)
{
	byte	MathCnt;						// Byte count for calculations
	byte	temp;
	*MathPtr++ = val & 0xff;
	*MathPtr++ = val >> 8;
	#if StackDataSize > 2
		temp = 0;
		if (BIT_TEST(val, 15)) temp--;
		for (MathCnt = StackDataSize-2; MathCnt != 0; MathCnt--)
		{
			*MathPtr++ = temp;
		}
	#endif
}

#inline
void DropStk()
{
	MathPtr -= StackDataSize;
}

long PopLong()
{
	DropStk();
	return *((long*)MathPtr);
}

// MathCarry = sign of *MathDstP
void signPtr()
{
	MathCarry = 0;
	if (BIT_TEST((*(MathDstP+StackDataSize-1)),7)) MathCarry = 1;
}

// Check sign of 1st on stack
void SignStk()
{
	MathDstP = MathPtr - StackDataSize;
	signPtr();
}

void PopStk(byte *ptr)
{
	byte	MathCnt;						// Byte count for calculations
	ptr += StackDataSize;
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		*--ptr = *--MathPtr;
	}
}

void PopStk16(byte *ptr)
{
	ptr++;
	MathPtr -= (StackDataSize-2);
	*ptr-- = *--MathPtr;
	*ptr = *--MathPtr;
}

// Swap *MathDstP and *MathSrcP
void SwapPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte SwapDstP;						// Swap scratch register
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		SwapDstP = *MathDstP;
		*MathDstP++ = *MathSrcP;
		*MathSrcP++ = SwapDstP;
	}
	MathDstP -= StackDataSize;
	MathSrcP -= StackDataSize;
}

// Swap 1st and 2nd on stack
void SwapStk()
{
	MathDstP = MathPtr - StackDataSize;
	MathSrcP = MathPtr - 2*StackDataSize;
	SwapPtr();
}

// *MathDstP = *MathSrcP
void dupPtr()
{
	byte	MathCnt;						// Byte count for calculations
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		*MathDstP++ = *MathSrcP++;
	}
	MathDstP -= StackDataSize;
	MathSrcP -= StackDataSize;
}

// Duplicate 1st on stack
void DupStk()
{
	MathPtr += StackDataSize;
	MathDstP = MathPtr - StackDataSize;
	MathSrcP = MathPtr - 2*StackDataSize;
	dupPtr();
}

// Copy 2nd on stack to next stack entry 
void OverStk()
{
	MathPtr += StackDataSize;
	MathDstP = MathPtr - StackDataSize;
	MathSrcP = MathPtr - 3*StackDataSize;
	dupPtr();
}

// Delete 2nd value on stack
void Del2ndStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	dupPtr();									// Copy 1st entry over 2nd entry
	DropStk();
}

// Restore last value popped
void RestoreStk()
{
	MathPtr += StackDataSize;
}

// *MathDstP = ~*MathDstP
void comPtr()
{
	byte	MathCnt;						// Byte count for calculations
	MathCnt = StackDataSize;
	FSR = MathDstP;
	#asm
com32a:
		comf		INDF,f
		incf		FSR,f
		decfsz	MathCnt,f
		goto		com32a
	#endasm
}

// Complement 1st on stack
void ComStk()
{
	MathDstP = MathPtr - StackDataSize;
	comPtr();
}

// *MathDstP << 1
// bit 0 = MathCarry
// MathCarry set according to high bit on exit
void RLPtr()
{
	byte	MathCnt;						// Byte count for calculations
	MathCnt = StackDataSize;
	FSR = MathDstP;
	RestoreCarry();
	#asm
rl32a:
		rlf			INDF,f
		incf		FSR,f
		decfsz	MathCnt,f
		goto		rl32a
	#endasm
	SaveCarry();
}

// Rotate right 1st on stack
// bit 0 = MathCarry
// MathCarry set according to high bit on exit
void RLStk()
{
	MathDstP = MathPtr - StackDataSize;
	RLPtr();
}

// *MathDstP << "shft"
// bit 0 = 0
// MathCarry set according to high bit on exit
void SLPtr(byte shft)
{
	while (shft)
	{
		MathCarry = 0;
		RLPtr();
		shft--;
	}
}

// Shift left 2nd on stack for count in 1st on stack
// bit 0 = 0
// MathCarry set according to high bit on exit
void SLStk()
{
	DropStk();
	MathDstP = MathPtr - StackDataSize;
	SLPtr(*MathPtr);
}

// *MathDstP >> 1
// High bit = MathCarry
// MathCarry set from bit 0 on exit
void RRPtr()
{
	byte	MathCnt;						// Byte count for calculations
	MathCnt = StackDataSize;
	FSR = MathDstP+StackDataSize-1;	// Start with uppermost byte
	RestoreCarry();
	#asm
rr32a:
		rrf			INDF,f
		decf		FSR,f
		decfsz	MathCnt,f
		goto		rr32a
	#endasm
	SaveCarry();
}

// Rotate right 1st on stack
// High bit = MathCarry
// MathCarry set from bit 0 on exit
void RRStk()
{
	MathDstP = MathPtr - StackDataSize;
	RRPtr();
}

// *MathDstP >> "shft"
// High bit = MathCarry
// MathCarry set from bit 0 on exit
void SRPtr(byte shft)
{
	while (shft)
	{
		if (MathCarry)
		{
			RRPtr();
			MathCarry = 1;
		}
		else
		{
			RRPtr();
			MathCarry = 0;
		}
		shft--;
	}
}

// Shift right 2nd on stack for count in 1st on stack
// High bit = MathCarry
// MathCarry set from bit 0 on exit
void SRStk()
{
	DropStk();
	MathDstP = MathPtr - StackDataSize;
	SRPtr(*MathPtr);
}

// *MathDstP = *MathDstP + *MathSrcP
// MathCarry set on exit if overflow
void addPtr()
{
	byte	AddDstP;						// Addition scratch register
	byte	MathCnt;						// Byte count for calculations
	byte	SaveDstP, SaveSrcP;
	SaveDstP = MathDstP;
	SaveSrcP = MathSrcP;
	MathCnt = StackDataSize;
	#asm
		bcf			STATUS,C				// No overflow yet
add32a:
		movf		SaveSrcP,w
		incf		SaveSrcP,f
		movwf		FSR
		movf		INDF,w
		movwf		AddDstP					// AddDstP = *SaveSrcP++
		movf		SaveDstP,w
		incf		SaveDstP,f
		movwf		FSR							// FSR = SaveDstP++
		movf		AddDstP,w
		btfsc		STATUS,C
		goto		add32c
		// Carry clear
add32b:
		addwf		indf,f
		goto		add32e
add32c:
		// Carry set
		incfsz	AddDstP,w				// Add one more for carry
		goto		add32b					// No overflow from carry, just add
		// W = 0x100 - overflow from carry
		addwf		indf,f
		bsf			STATUS,C				// Overflow from carry
add32e:
		decfsz	MathCnt,f
		goto		add32a
	#endasm
	SaveCarry();
}

// 2nd on stack += 1st on stack
// 1st on stack dropped
void AddStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	addPtr();
	DropStk();
}

// *MathDstP = *MathDstP - *MathSrcP
// MathCarry set on exit if no underflow
void subPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte	SubDstP;						// Subtraction scratch register
	byte	SaveDstP, SaveSrcP;
	SaveDstP = MathDstP;
	SaveSrcP = MathSrcP;
	MathCnt = StackDataSize;
	status_c = 1;							// No underflow yet
	#asm
sub32a:
		movf		SaveSrcP,w
		incf		SaveSrcP,f
		movwf		FSR
		movf		INDF,w
		movwf		SubDstP					// SubDstP = *SaveSrcP++
		movf		SaveDstP,w
		incf		SaveDstP,f
		movwf		FSR							// FSR = SaveDstP++
		movf		SubDstP,w
		btfss		STATUS,C
		goto		sub32c
		// Carry set - no underflow
sub32b:
		subwf		indf,f
		goto		sub32d
sub32c:
		// Carry clear - underflow from last time
		incfsz	SubDstP,w				// Subtract one more for carry
		goto		sub32b					// No underflow from carry, just subtract
		// W = 0x100 - underflow from carry
		subwf		indf,f
		bcf			STATUS,C				// Underflow from carry
sub32d:
		decfsz	MathCnt,f
		goto		sub32a
	#endasm
	SaveCarry();
}


// *MathDstP = *MathDstP compared with *MathSrcP
// MathCarry set on exit if no underflow
void cmpPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte	SubDstP;						// Subtraction scratch register
	byte	SaveDstP, SaveSrcP;
	SaveDstP = MathDstP;
	SaveSrcP = MathSrcP;
	MathCnt = StackDataSize;
	status_c = 1;							// No underflow yet
	#asm
cmp32a:
		movf		SaveSrcP,w
		incf		SaveSrcP,f
		movwf		FSR
		movf		INDF,w
		movwf		SubDstP					// SubDstP = *SaveSrcP++
		movf		SaveDstP,w
		incf		SaveDstP,f
		movwf		FSR							// FSR = SaveDstP++
		movf		SubDstP,w
		btfss		STATUS,C
		goto		cmp32c
		// Carry set - no underflow
cmp32b:
		subwf		indf,w
		goto		cmp32d
cmp32c:
		// Carry clear - underflow from last time
		incfsz	SubDstP,w				// Subtract one more for carry
		goto		cmp32b					// No underflow from carry, just subtract
		// W = 0x100 - underflow from carry
		subwf		indf,w
		bcf			STATUS,C				// Underflow from carry
cmp32d:
		decfsz	MathCnt,f
		goto		cmp32a
	#endasm
	SaveCarry();
}


// 2nd on stack -= 1st on stack
// 1st on stack dropped
void SubStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	subPtr();
	DropStk();
}

// 2nd on stack - 1st on stack
// 2nd on stack not altered
// 1st on stack dropped
void CmpStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	cmpPtr();
	DropStk();
}

// *MathDstP &= *MathSrcP
void andPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte	AndDstP;						// AND scratch register
	byte	SaveDstP, SaveSrcP;
	SaveDstP = MathDstP;
	SaveSrcP = MathSrcP;
	MathCnt = StackDataSize;
	#asm
and32a:
		movf		SaveSrcP,w
		incf		SaveSrcP,f
		movwf		FSR
		movf		INDF,w
		movwf		AndDstP					// AndDstP = *SaveSrcP++
		movf		SaveDstP,w
		incf		SaveDstP,f
		movwf		FSR							// FSR = SaveDstP++
		movf		AndDstP,w
		andwf		indf,f
		decfsz	MathCnt,f
		goto		and32a
	#endasm
}

// 2nd on stack &= 1st on stack
// 1st on stack dropped
void AndStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	andPtr();
	DropStk();
}

// *MathDstP ++
void incPtr()
{
	byte	MathCnt;						// Byte count for calculations
	MathCnt = StackDataSize;
	FSR = MathDstP;
	#asm
inc32a:
		incf		INDF,f					// Overflow if incremented to 0
		btfss		STATUS,Z
		goto		inc32b					// Done if no overflow
		incf		FSR,f
		decfsz	MathCnt,f
		goto		inc32a
inc32b:
	#endasm
}

// Increment 1st on stack
// MathCarry set according to result
void IncStk()
{
	MathDstP = MathPtr - StackDataSize;
	incPtr();
}

// *MathDstP --
void decPtr()
{
	byte	MathCnt;						// Byte count for calculations
	MathCnt = StackDataSize;
	FSR = MathDstP;
	#asm
dec32a:
		decf		INDF,f
		incf		INDF,w					// Underflow if original value was 0
		btfss		STATUS,Z
		goto		dec32b					// Done if no underflow (not Z)
		incf		FSR,f
		decfsz	MathCnt,f
		goto		dec32a
dec32b:
	#endasm
}

// Decrement 1st on stack
// MathCarry set according to result
void DecStk()
{
	MathDstP = MathPtr - StackDataSize;
	decPtr();
}


// *MathDstP = -(*MathDstP)
void negPtr()
{
	byte	MathCnt;						// Byte count for calculations

	MathCnt = StackDataSize;
	FSR = MathDstP;
	#asm
com32a:
		comf		INDF,f
		incf		FSR,f
		decfsz	MathCnt,f
		goto		com32a
	#endasm

	FSR = MathDstP;
	#asm
inc32a:
		incf		INDF,f					// Overflow if incremented to 0
		btfss		STATUS,Z
		goto		inc32b					// Done if no overflow
		incf		FSR,f
		decfsz	MathCnt,f
		goto		inc32a
inc32b:
	#endasm
}


// Negate 1st on stack
void NegStk()
{
	MathDstP = MathPtr - StackDataSize;
	negPtr();
}

// Absolute value of *MathDstP
// MathCarry set according to sign of original value
void AbsPtr()
{
	SignPtr();
	if (MathCarry)
	{
		// Negative number
		negPtr();
	}
}

// Absolute value of 1st on stack
// MathCarry set according to sign of original value
void AbsStk()
{
	MathDstP = MathPtr - StackDataSize;
	AbsPtr();
}

// Force value on stack to fit into 16 bits
void StkMake16()
{
	SignStk();
	PushStkSLong(0x7fff);		// Largest positive value
	// Look for 2nd on stack <= 1st on stack
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	if (MathCarry)
	{
		// Smallest negative value
		comStk();
		// Look for 1st on stack <= 2nd on stack
		MathSrcP = MathPtr - 2*StackDataSize;
		MathDstP = MathPtr - StackDataSize;
	}
	CmpPtr();
	if (MathCarry)
	{
		// No underflow
		SwapStk();
	}
	DropStk();
}

// *MathDstP/1 = (*MathDstP) * (*MathSrcP) (unsigned, MSB of product in *MathSrcP)
void mulPtr()
{
	byte	MulDstP;						// Multiplication scratch register #1
	byte	MulSrcP;						// Multiplication scratch register #2
	byte	MathCnt;						// Byte count for calculations
	byte	MulCnt;							// Multiplication count register
	MulDstP = MathDstP;
	MulSrcP = MathSrcP;
	MathSrcP = MathDstP;
	MathDstP = MulTPtr;
	DupPtr();									// Copy 1st entry to scratch area
	MathDstP = MulDstP;
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		*MathDstP++ = 0;
	}
	for (MulCnt = 8*StackDataSize; MulCnt != 0; MulCnt--)
	{
		MathDstP = MulDstP;
		MathCarry = 0;
		RLPtr();
		MathDstP = MulSrcP;
		RLPtr();
		if (MathCarry)
		{
			MathDstP = MulDstP;
			MathSrcP = MulTPtr;
			AddPtr();
			if (MathCarry)
			{
				MathSrcP = MulDstP;
				incPtr();
			}
		}
	}
	MathDstP = MulDstP;
	MathSrcP = MulSrcP;
}

// *MathDstP/1 = (*MathDstP) * (*MathSrcP) (signed, MSB of product in *MathSrcP)
void mulsPtr()
{
	byte	MulDstP;						// Multiplication scratch register #1
	byte	MulSrcP;						// Multiplication scratch register #2
	bit	sign; // Sign of product
	MulDstP = MathDstP;
	MulSrcP = MathSrcP;

	signPtr();
	sign = MathCarry;
	if (MathCarry) negPtr();

	MathDstP = MulSrcP;
	signPtr();
	if (MathCarry)
	{
		sign = !sign;
		negPtr();
	}
	MathSrcP = MulSrcP;
	MathDstP = MulDstP;
	mulPtr();
	if (sign)
	{
		MathDstP = MulDstP;
		comPtr();
		MathDstP = MulSrcP;
		comPtr();
		MathDstP = MulDstP;
		incPtr();
		if (MathCarry)
		{
			MathDstP = MulSrcP;
			incPtr();
		}
	}
	MathDstP = MulDstP;
	MathSrcP = MulSrcP;
}

void MulStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	mulPtr();
	#ifdef dMathDouble
		if (!MathDouble)
	#endif
	DropStk(); // Drop high order portion if single-precision
}

void MulsStk()
{
	MathDstP = MathPtr - 2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	mulsPtr();
	#ifdef dMathDouble
		if (!MathDouble)
	#endif
	DropStk(); // Drop high order portion if single-precision
}

// *MathDstP = (*MathDstP) / (*MathSrcP) (unsigned)
// *MathSrcP = (*MathDstP) % (*MathSrcP) (unsigned)
// Dividend and quotient are double-precision if MathDouble set
void divPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte DivDstP;							// Division scratch register #1
	byte DivSrcP;							// Division scratch register #2
	byte DivCnt;							// Division count register
	DivDstP = MathDstP;
	DivSrcP = MathSrcP;
	MathDstP = DivTPtr;
	DupPtr();									// Copy divisor to scratch area
	MathDstP = DivSrcP;
	for (MathCnt = StackDataSize; MathCnt != 0; MathCnt--)
	{
		*MathDstP++ = 0;				// Remainder
	}
	for
	(
		DivCnt =
		#ifdef dMathDouble
			MathDouble ? 8*2*StackDataSize :
		#endif
		8 * StackDataSize;
		DivCnt != 0;
		DivCnt--
	)
	{
		MathDstP = DivDstP;
		MathCarry = 0;
		RLPtr();
		#ifdef dMathDouble
			if (MathDouble)
			{
				MathDstP = DivDstP+StackDataSize;
				RLPtr();
			}
		#endif
		MathDstP = DivSrcP;
		RLPtr();								// Rotate dividend through remainder

		MathDstP = DivSrcP;
		MathSrcP = DivTPtr;
		if (!MathCarry)
		{
			// No overflow from shift, compare first
			cmpPtr();
			MathDstP = DivSrcP;
			MathSrcP = DivTPtr;		// Restore registers
		}
		if (MathCarry)
		{
			subPtr();
			*DivDstP |= 1;
		}
	}
	MathDstP = DivDstP;
	MathSrcP = DivSrcP;
}

// *MathDstP = (*MathDstP) / (*MathSrcP) (signed)
// *MathSrcP = (*MathDstP) % (*MathSrcP) (signed)
// Dividend and quotient are double-precision if MathDouble set
void divsPtr()
{
	byte	MathCnt;						// Byte count for calculations
	byte DivDstP;							// Division scratch register #1
	byte DivSrcP;							// Division scratch register #2
	bit	signq;								// Sign of quotient
	bit	signr;								// Sign of remainder
	DivDstP = MathDstP;
	DivSrcP = MathSrcP;

	#ifdef dMathDouble
		if (MathDouble) MathDstP += StackDataSize;
	#endif
	signPtr();
	signq = MathCarry;
	signr = MathCarry;
	if (MathCarry)
	{
		MathDstP = DivDstP;
		comPtr();
		#ifdef dMathDouble
			if (MathDouble)
			{
				MathDstP = DivDstP+StackDataSize;
				comPtr();
			}
		#endif
		MathDstP = DivDstP;
		incPtr();
		#ifdef dMathDouble
			if (MathDouble)
			{
				if (MathCarry)
				{
					MathDstP = DivDstP+StackDataSize;
					incPtr();
				}
			}
		#endif
	}

	MathDstP = DivSrcP;
	signPtr();
	if (MathCarry)
	{
		signq = !signq;
		negPtr();
	}
	MathSrcP = DivSrcP;
	MathDstP = DivDstP;
	divPtr();
	if (signq)
	{
		MathDstP = DivDstP;
		comPtr();
		#ifdef dMathDouble
			if (MathDouble)
			{
				MathDstP = DivDstP+StackDataSize;
				comPtr();
			}
		#endif
		MathDstP = DivDstP;
		incPtr();
		#ifdef dMathDouble
			if (MathDouble)
			{
				if (MathCarry)
				{
					MathDstP = DivDstP+StackDataSize;
					incPtr();
				}
			}
		#endif
	}
	if (signr)
	{
		// Sign of remainder is sign of dividend
		MathDstP = DivSrcP;
		negPtr();
	}
	MathDstP = DivDstP;
	MathSrcP = DivSrcP;
}

// 1st = 2nd on stack / 1st on stack (unsigned)
void DivStk()
{
	MathDstP =
	#ifdef dMathDouble
		MathDouble ? MathPtr-3*StackDataSize :
	#endif
	MathPtr-2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	divPtr();
	DropStk();
}

// 1st on stack = 2nd on stack / 1st on stack (signed)
void DivSStk()
{
	MathDstP =
	#ifdef dMathDouble
		MathDouble ? MathPtr-3*StackDataSize :
	#endif
	MathPtr-2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	divsPtr();
	DropStk();
}

// 2nd on stack = 2nd on stack / 1st on stack (unsigned)
// 1st on stack = 2nd on stack % 1st on stack (unsigned)
void DivRStk()
{
	MathDstP =
	#ifdef dMathDouble
		MathDouble ? MathPtr-3*StackDataSize :
	#endif
	MathPtr-2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	divPtr();
}


// 2nd on stack = 2nd on stack / 1st on stack (signed)
// 1st on stack = 2nd on stack % 1st on stack (signed)
void DivSRStk()
{
	MathDstP =
	#ifdef dMathDouble
		MathDouble ? MathPtr-3*StackDataSize :
	#endif
	MathPtr-2*StackDataSize;
	MathSrcP = MathPtr - StackDataSize;
	divsPtr();
}

#endif //#ifndef __MATH32_C
