Files
OpenEPaperLink/zbs243_shared/cpu/8051/asmUtil.c
2023-03-27 15:32:37 +02:00

1503 lines
30 KiB
C

#include "asmUtil.h"
#include "cpu.h"
#pragma callee_saves mathPrvU8bitswap
uint16_t mathPrvU16from2xU8(uint8_t hi, uint8_t lo) __reentrant __naked
{
__asm__(
" mov DPH, DPL \n"
" pop B \n"
" pop A \n"
" pop DPL \n"
" push DPL \n"
" push A \n"
" push B \n"
" ret \n"
);
(void)hi;
(void)lo;
}
//a is hi
uint32_t mathPrvU32from4xU8(uint8_t hi, uint8_t midhi, uint8_t midlo, uint8_t lo) __reentrant __naked
{
__asm__(
" push _R0 \n"
" mov A, #-5 \n" //point to first pushed arg (last param - lo)
" add A, sp \n"
" mov R0, A \n"
" mov A, DPL \n"
" mov DPL, @R0 \n"
" inc R0 \n"
" mov DPH, @R0 \n"
" inc R0 \n"
" mov B, @R0 \n"
" pop _R0 \n"
" ret \n"
);
(void)hi;
(void)midhi;
(void)midlo;
(void)lo;
}
#pragma callee_saves mathPrvU8bitswap
uint8_t mathPrvU8bitswap(uint8_t val) __reentrant __naked
{
__asm__(
" mov B, #8 \n"
"00003$: \n"
" xch A, DPL \n"
" rrc A \n"
" xch A, DPL \n"
" rlc A \n"
" djnz B, 00003$ \n"
" xch A, DPL \n"
" ret \n"
);
(void)val;
}
#pragma callee_saves mathPrvI16Asr1
int16_t mathPrvI16Asr1(int16_t val) __reentrant __naked
{
__asm__(
" mov A, DPH \n"
" mov C, A.7 \n"
" rrc A \n"
" mov DPH, A \n"
" mov A, DPL \n"
" rrc A \n"
" mov DPL, A \n"
" ret \n"
);
(void)val;
}
#pragma callee_saves mathPrvMul8x8
uint16_t mathPrvMul8x8(uint8_t a, uint8_t b) __reentrant __naked
{
//return expected in DPTR, first param is in DPL, second on stack
__asm__(
//grab param into B
" pop DPH \n\t"
" pop A \n\t"
" pop B \n\t"
" push B \n\t"
" push A \n\t"
" push DPH \n\t"
//second param into A
" mov A, DPL \n\t"
//do the deed
" mul AB \n\t"
//return results
" mov DPL, A \n\t"
" mov DPH, B \n\t"
" ret \n\t"
);
(void)a;
(void)b;
}
#pragma callee_saves mathPrvMul16x8
uint32_t mathPrvMul16x8(uint16_t a, uint8_t b) __reentrant __naked
{
//return expected in A:B:DPTR, first param is in DPTR, second on stack
__asm__(
//save r0
" push _R0 \n\t"
//get 2nd param into a & r0
" mov A, SP \n\t"
" add A, #-0x03 \n\t"
" mov R0, A \n\t"
" mov A, @R0 \n\t"
" mov R0, A \n\t"
//get first param.lo into B
" mov B, DPL \n\t"
//mul
" mul AB \n\t"
//lower result byte is ready!
" mov DPL, A \n\t"
//save upper in r0, get 2nd param into A
" mov A, R0 \n\t"
" mov R0, B \n\t"
//get first param.hi into B
" mov B, DPH \n\t"
//mul
" mul AB \n\t"
//add in the carry from before
" add A, R0 \n\t"
//produce middle byte
" mov DPH, A \n\t"
//calc high byte
" mov A, B \n\t"
" addc A, #0 \n\t"
" mov B, A \n\t"
//set high high byte to 0 (guaranteed)
" clr A \n\t"
//get out
" pop _R0 \n\t"
" ret \n\t"
);
(void)a;
(void)b;
}
#pragma callee_saves mathPrvMul32x8
uint32_t mathPrvMul32x8(uint32_t a, uint8_t b) __reentrant __naked
{
//return expected in A:B:DPTR, first param is in DPTR, second on stack
__asm__(
//save r0
" push _R0 \n\t"
" push _R1 \n\t"
//save A and B
" push A \n"
" push B \n"
//get second param into R0
" mov A, #-6 \n"
" add A, sp \n"
" mov R0, A \n"
" mov _R0, @R0 \n"
//low
" mov A, DPL \n"
" mov B, R0 \n"
" mul AB \n"
" mov DPL, A \n"
" mov R1, B \n"
//mid.lo
" mov A, DPH \n"
" mov B, R0 \n"
" mul AB \n"
" add A, R1 \n"
" mov DPH, A \n"
" mov A, B \n"
" addc A, #0 \n"
" mov R1, A \n"
//mid.hi
" pop A \n"
" mov B, R0 \n"
" mul AB \n"
" add A, R1 \n"
" xch A, B \n"
" addc A, #0 \n"
" mov R1, A \n"
//hi
" pop A \n"
" push B \n"
" mov B, R0 \n"
" mul AB \n"
" add A, R1 \n"
" pop B \n"
//get out
" pop _R1 \n\t"
" pop _R0 \n\t"
" ret \n\t"
);
(void)a;
(void)b;
}
#pragma callee_saves mathPrvMul16x16
uint32_t mathPrvMul16x16(uint16_t a, uint16_t b) __reentrant __naked
{
//return expected in A:B:DPTR, first param is in DPTR, second on stack (low byte was pushed first)
__asm__(
//save r0,r1,r2
" push _R0 \n\t"
" push _R1 \n\t"
" push _R2 \n\t"
//get 2nd param into r1:r0
" mov A, SP \n\t"
" add A, #-0x05 \n\t"
" mov R0, A \n\t"
" mov A, @R0 \n\t"
" mov R1, A \n\t"
" dec R0 \n\t"
" mov A, @R0 \n\t"
" mov R0, A \n\t"
//mul low bytes, save low result byte
" mov B, DPL \n\t"
" mul AB \n\t"
" push A \n\t"
//save high byte
" mov R2, B \n\t"
//mul p2.lo * p1.hi. add in high from the low multiplication. we know this fits in 16 bits!
" mov A, DPH \n\t"
" mov B, R0 \n\t"
" mul AB \n\t"
" add A, R2 \n\t"
" mov R0, A \n\t" //save intermediate's lo in R0
" mov A, B \n\t"
" addc A, #0 \n\t"
" mov R2, A \n\t" //save intermediate's hi in R2
//mul p2.hi * p1.lo, add in intermediate result
" mov A, R1 \n\t"
" mov B, DPL \n\t"
" mul AB \n\t"
" add A, R0 \n\t" //calc intermediate's lo
" push A \n\t" //push it
" mov A, B \n\t"
" addc A, R2 \n\t"
" mov R2, A \n\t" //calc intermediate's hi in R2
" mov A, #0 \n\t"
" addc A, #0 \n\t" //calc high byte so far
" mov R0, A \n\t" //store in R0
//mul high bytes
" mov A, R1 \n\t"
" mov B, DPH \n\t"
" mul AB \n\t"
" add A, R2 \n\t"
" mov R2, A \n\t" //final value for intermediate's high
" mov A, B \n\t"
" addc A, R0 \n\t" //final high value is ready
//produce the rest of the result bytes
" mov B, R2 \n\t"
" pop DPH \n\t"
" pop DPL \n\t"
//return
" pop _R2 \n\t"
" pop _R1 \n\t"
" pop _R0 \n\t"
" ret \n\t"
);
(void)a;
(void)b;
}
//pushes R0..R2, gets second param into r1:r0
#pragma callee_saves u64_start
static void u64_start(void) __reentrant __naked
{
__asm__(
" pop A \n" //get ret addr
" pop B \n" //get ret addr
" push _R0 \n"
" push _R1 \n"
" push _R2 \n"
" push B \n" //re-push ret addr
" push A \n"
" mov a, #0xf8 \n" // DPTR = pushed_arg
" add a, sp \n"
" mov R1, a \n"
" mov a, @R1 \n"
" mov R0, a \n"
" inc R1 \n"
" mov a, @R1 \n"
" mov R1, a \n"
" ret \n"
);
}
//jump to this, do not call it
//does not clobber anything
#pragma callee_saves u64_end
static void u64_end(void) __reentrant __naked
{
__asm__(
" pop _R2 \n"
" pop _R1 \n"
" pop _R0 \n"
" ret \n"
);
}
#pragma callee_saves mathPrvSwapDptrR1R0
void mathPrvSwapDptrR1R0(void) __reentrant __naked
{
__asm__(
" xch A, R1 \n\t"
" xch A, DPH \n\t"
" xch A, R1 \n\t"
" xch A, R0 \n\t"
" xch A, DPL \n\t"
" xch A, R0 \n\t"
" ret \n\t"
);
}
#pragma callee_saves u64_copy
void u64_copy(uint64_t __xdata *dst, const uint64_t __xdata *src) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)dst;
(void)src;
}
void u64_copyFromCode(uint64_t __xdata *dst, const uint64_t __code *src) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" clr a \n"
" movc a, @a+dptr \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)dst;
(void)src;
}
#pragma callee_saves u64_add
void u64_add(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" clr C \n"
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" mov _R2, a \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" addc a, R2 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)lhsP;
(void)rhsP;
}
#pragma callee_saves u64_and
void u64_and(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" mov _R2, a \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" anl a, R2 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)lhsP;
(void)rhsP;
}
#pragma callee_saves u64_sub
void u64_sub(uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" clr C \n"
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" mov _R2, a \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" subb a, R2 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)lhsP;
(void)rhsP;
}
#pragma callee_saves u64_isLt
__bit u64_isLt(const uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" clr C \n"
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" mov _R2, a \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" subb a, R2 \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)lhsP;
(void)rhsP;
}
#pragma callee_saves u64_isEq
__bit u64_isEq(const uint64_t __xdata *lhsP, const uint64_t __xdata *rhsP) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" mov _R2, a \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" xrl a, R2 \n"
" jnz 00004$ \n"
" djnz b, 00003$ \n"
" setb C \n"
" ljmp _u64_end \n"
"00004$: \n"
" clr C \n"
" ljmp _u64_end \n"
);
(void)lhsP;
(void)rhsP;
}
//c is set, A is what to add to each limb
#pragma callee_saves u64_incdec
static void u64_incdec(uint64_t __xdata *dst) __reentrant __naked
{
__asm__(
" xch A, R0 \n"
" push A \n"
" mov b, #8 \n" //repeat 8 times:
"00003$: \n"
" movx a, @dptr \n"
" addc a, R0 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" pop _R0 \n"
" ret \n"
);
(void)dst;
}
#pragma callee_saves u64_inc
void u64_inc(uint64_t __xdata *dst) __reentrant __naked
{
__asm__(
" setb C \n"
" clr A \n"
" ljmp _u64_incdec \n"
);
(void)dst;
}
#pragma callee_saves u64_dec
void u64_dec(uint64_t __xdata *dst) __reentrant __naked
{
__asm__(
" clr C \n"
" mov A, #0xFF \n"
" ljmp _u64_incdec \n"
);
(void)dst;
}
#pragma callee_saves xMemSet
void xMemSet(void __xdata* mem, uint8_t val, uint16_t num) __reentrant __naked
{
__asm__(
" push _R0 \n"
" push _R1 \n"
" mov A, #-6 \n"
" add A, sp \n"
" mov R0, A \n"
" mov A, @R0 \n" //num.lo
" mov B, A \n"
" inc R0 \n"
" mov _R1, @R0 \n" //num.hi
" orl A, R1 \n" //zero check
" jz 00002$ \n" //num is R1:B
" inc R0 \n"
" mov _R0, @R0 \n" //val
"00003$: \n"
" mov A, R0 \n"
" movx @DPTR, A \n"
" inc DPTR \n"
" mov A, #0xff \n"
" add A, B \n"
" mov B, A \n"
" mov A, #0xff \n"
" addc A, R1 \n"
" mov _R1, A \n"
" orl A, B \n"
" jnz 00003$ \n"
"00002$: \n"
" pop _R1 \n"
" pop _R0 \n"
" ret \n"
);
(void)mem;
(void)val;
(void)num;
}
#pragma callee_saves xMemEqual
__bit xMemEqual(const void __xdata* memA, const void __xdata* memB, uint8_t num) __reentrant __naked
{
__asm__(
" push _R0 \n"
" push _R1 \n"
" push _R2 \n"
" mov a, #-7 \n"
" add a, sp \n"
" mov R1, a \n"
" mov A, @R1 \n"
" setb C \n" //equal if len is zero
" jz 00004$ \n"
" mov B, A \n"
" inc R1 \n"
" mov _R0, @R1 \n"
" inc R1 \n"
" mov _R1, @R1 \n"
" clr C \n"
"00003$: \n"
" movx a, @dptr \n"
" mov _R2, a \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" xrl a, R2 \n"
" jnz 00004$ \n"
" djnz b, 00003$ \n"
" setb C \n"
"00004$: \n"
" pop _R2 \n"
" pop _R1 \n"
" pop _R0 \n"
" ret \n"
);
(void)memA;
(void)memB;
(void)num;
}
#pragma callee_saves xMemCopy
void xMemCopy(void __xdata* dst, const void __xdata* src, uint16_t num) __reentrant __naked
{
__asm__(
" push _R0 \n"
" push _R1 \n"
" push _R2 \n"
" mov A, #-8 \n"
" add A, sp \n"
" mov R1, A \n"
" mov A, @R1 \n"
" mov B, A \n"
" inc R1 \n"
" mov _R2, @R1 \n" //R2:B is length
" orl A, R2 \n"
" jz 00004$ \n" //handle zero length
" inc R1 \n"
" mov _R0, @R1 \n"
" inc R1 \n"
" mov _R1, @R1 \n" //R1:R0 is src
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx @DPTR, A \n"
" inc DPTR \n"
" mov A, #0xff \n"
" add A, B \n"
" mov B, A \n"
" mov A, #0xff \n"
" addc A, R2 \n"
" mov _R2, A \n"
" orl A, B \n"
" jnz 00003$ \n"
"00004$: \n"
" pop _R2 \n"
" pop _R1 \n"
" pop _R0 \n"
" ret \n"
);
(void)dst;
(void)src;
(void)num;
}
#pragma callee_saves xMemCopyShort
void xMemCopyShort(void __xdata* dst, const void __xdata* src, uint8_t num) __reentrant __naked
{
__asm__(
" push _R0 \n"
" push _R1 \n"
" push _R2 \n"
" mov a, #-7 \n"
" add a, sp \n"
" mov R1, a \n"
" mov A, @R1 \n"
" jz 00004$ \n"
" mov B, A \n"
" inc R1 \n"
" mov _R0, @R1 \n"
" inc R1 \n"
" mov _R1, @R1 \n"
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
"00004$: \n"
" pop _R2 \n"
" pop _R1 \n"
" pop _R0 \n"
" ret \n"
);
(void)dst;
(void)src;
(void)num;
}
#pragma callee_saves xStrLen
uint16_t xStrLen(const char __xdata *str) __reentrant __naked
{
__asm__(
" push DPH \n"
" push DPL \n"
"00003$: \n"
" movx a, @dptr \n"
" jz 00002$ \n"
" inc dptr \n"
" sjmp 00003$ \n"
"00002$: \n"
" clr C \n"
" mov A, DPL \n"
" pop B \n"
" subb A, B \n"
" mov DPL, A \n"
" mov A, DPH \n"
" pop B \n"
" subb A, B \n"
" mov DPH, A \n"
" ret \n"
);
(void)str;
}
#pragma callee_saves static mathPrvDivMod32x16
static uint32_t mathPrvDivMod32x16(uint32_t num, uint16_t denom) __reentrant __naked
{
//PSW.5 determines if to produce quotient (0) or remainder(1)
__asm__(
" push _R3 \n"
" push _R2 \n"
" push _R1 \n"
" push _R0 \n"
" push A \n"
" push B \n"
" push DPH \n"
" push DPL \n"
" mov R1, sp \n" //R1: point to bottom byte of numerator
//get denom -> B:R0
" mov A, #-10 \n"
" add A, sp \n"
" mov R0, A \n" //R0 = &denom.hi
" mov B, @R0 \n" //B = denom.hi
" dec R0 \n"
" mov _R0, @R0 \n" //R0 = denom.lo
//shift it off (in B:R0), record how many iters we'll need (in DPL), generate proper top 8 bits for result mask (in R3:R2)
" mov _R2, #1 \n"
" mov _R3, #0 \n"
" mov DPL, #17 \n"
"00002$: \n"
" mov C, B.7 \n"
" jc 00003$ \n"
" clr C \n"
" mov A, R0 \n"
" rlc A \n"
" mov R0, A \n"
" mov A, B \n"
" rlc A \n"
" mov B, A \n"
" clr C \n"
" mov A, R2 \n"
" rlc A \n"
" mov R2, A \n"
" mov A, R3 \n"
" rlc A \n"
" mov R3, A \n"
" inc DPL \n"
" sjmp 00002$ \n"
"00003$: \n"
" clr A \n"
//push result_mask to stack
" push _R3 \n"
" push _R2 \n"
" push A \n"
" push A \n"
" mov R2, sp \n" //R2: point to bottom byte of result_mask
//push denom.shifted to stack
" push B \n"
" push _R0 \n"
" push A \n"
" push A \n"
" mov R0, sp \n" //R0: point to bottom byte of denom.shifted
//push result to stack
" push A \n"
" push A \n"
" push A \n"
" push A \n"
" mov R3, sp \n" //R3: point to bottom byte of result
//loop-divide
"00088$: \n"
// check if denom.shifted >= num
" push _R0 \n"
" push _R1 \n"
" clr C \n"
" mov DPH, #4 \n"
"00001$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" dec R1 \n"
" subb A, B \n"
" djnz DPH, 00001$ \n"
" pop _R1 \n"
" pop _R0 \n"
" jc 00099$ \n" //no? skip this round
//subtract
" push _R0 \n"
" push _R1 \n"
" clr C \n"
" mov DPH, #4 \n"
"00004$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" subb A, B \n"
" mov @R1, A \n"
" dec R1 \n"
" djnz DPH, 00004$ \n"
//keep r0 & r1 pushed
//set bit in result
//r0 & r1 still pushed
" mov _R0, _R2 \n"
" mov _R1, _R3 \n"
" mov DPH, #4 \n"
"00005$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" orl A, B \n"
" mov @R1, A \n"
" dec R1 \n"
" djnz DPH, 00005$ \n"
" pop _R1 \n"
" pop _R0 \n"
//set up next iteration
"00099$: \n"
// shift denom right one (pointer ends up where needed)
" mov A, #0xfc \n"
" add A, R0 \n"
" mov R0, A \n"
" clr C \n"
" mov DPH, #4 \n"
"00006$: \n"
" inc R0 \n"
" mov A, @R0 \n"
" rrc A \n"
" mov @R0, A \n"
" djnz DPH, 00006$ \n"
// shift result mask right one
" push _R0 \n"
" mov A, #0xfc \n"
" add A, R2 \n"
" mov R0, A \n"
" clr C \n"
" mov DPH, #4 \n"
"00007$: \n"
" inc R0 \n"
" mov A, @R0 \n"
" rrc A \n"
" mov @R0, A \n"
" djnz DPH, 00007$ \n"
" pop _R0 \n"
//check on loop limit
" djnz DPL, 00088$ \n"
//we're done. undo the terrible things we've done to the stack and get the result
//quotient return?
" jb PSW.5, 00009$ \n"
//return quotient
" pop DPL \n"
" pop DPH \n"
" pop B \n"
" pop _R0 \n"
"00009$: \n"
//now clear up the rest
" mov A, #-12 \n"
" add A, sp \n"
" mov sp, A \n"
//remainder return?
" jnb PSW.5, 00010$ \n"
//return quotient
" pop DPL \n"
" pop DPH \n"
" pop B \n"
" pop _R0 \n"
"00010$: \n"
" mov A, R0 \n"
//pop off regs
" pop _R0 \n"
" pop _R1 \n"
" pop _R2 \n"
" pop _R3 \n"
" ret \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves static mathPrvDiv32x16
uint32_t mathPrvDiv32x16(uint32_t num, uint16_t denom) __reentrant __naked
{
__asm__(
" clr PSW.5 \n"
" ljmp _mathPrvDivMod32x16 \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves static mathPrvDiv32x16
uint16_t mathPrvMod32x16(uint32_t num, uint16_t denom) __reentrant __naked
{
__asm__(
" setb PSW.5 \n"
" ljmp _mathPrvDivMod32x16 \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves mathPrvDiv32x8
uint32_t mathPrvDiv32x8(uint32_t num, uint8_t denom) __reentrant __naked
{
__asm__(
" push _R3 \n"
" push _R2 \n"
" push _R1 \n"
" push _R0 \n"
" push A \n"
" push B \n"
" push DPH \n"
" push DPL \n"
" mov R1, sp \n" //R1: point to bottom byte of numerator
//get denom -> B
" mov A, #0xf6 \n"
" add A, sp \n"
" mov R0, A \n"
" mov B, @R0 \n"
//shift it off (in B), record how many iters we'll need (in DPL), generate proper top 8 bits for result mask (in A)
" mov A, #1 \n"
" mov DPL, #25 \n"
"00002$: \n"
" mov C, B.7 \n"
" jc 00003$ \n"
" rl A \n"
" xch A, B \n"
" rl A \n"
" xch A, B \n"
" inc DPL \n"
" sjmp 00002$ \n"
"00003$: \n"
//push result_mask to stack
" push A \n"
" clr A \n"
" push A \n"
" push A \n"
" push A \n"
" mov R2, sp \n" //R2: point to bottom byte of result_mask
//push denom.shifted to stack
" push B \n"
" push A \n"
" push A \n"
" push A \n"
" mov R0, sp \n" //R0: point to bottom byte of denom.shifted
//push result to stack
" push A \n"
" push A \n"
" push A \n"
" push A \n"
" mov R3, sp \n" //R3: point to bottom byte of result
//loop-divide
"00088$: \n"
// check if denom.shifted >= num
" push _R0 \n"
" push _R1 \n"
" clr C \n"
" mov DPH, #4 \n"
"00001$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" dec R1 \n"
" subb A, B \n"
" djnz DPH, 00001$ \n"
" pop _R1 \n"
" pop _R0 \n"
" jc 00099$ \n" //no? skip this round
//subtract
" push _R0 \n"
" push _R1 \n"
" clr C \n"
" mov DPH, #4 \n"
"00004$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" subb A, B \n"
" mov @R1, A \n"
" dec R1 \n"
" djnz DPH, 00004$ \n"
//keep r0 & r1 pushed
//set bit in result
//r0 & r1 still pushed
" mov _R0, _R2 \n"
" mov _R1, _R3 \n"
" mov DPH, #4 \n"
"00005$: \n"
" mov B, @R0 \n"
" dec R0 \n"
" mov A, @R1 \n"
" orl A, B \n"
" mov @R1, A \n"
" dec R1 \n"
" djnz DPH, 00005$ \n"
" pop _R1 \n"
" pop _R0 \n"
//set up next iteration
"00099$: \n"
// shift denom right one (pointer ends up where needed)
" mov A, #0xfc \n"
" add A, R0 \n"
" mov R0, A \n"
" clr C \n"
" mov DPH, #4 \n"
"00006$: \n"
" inc R0 \n"
" mov A, @R0 \n"
" rrc A \n"
" mov @R0, A \n"
" djnz DPH, 00006$ \n"
// shift result mask right one
" push _R0 \n"
" mov A, #0xfc \n"
" add A, R2 \n"
" mov R0, A \n"
" clr C \n"
" mov DPH, #4 \n"
"00007$: \n"
" inc R0 \n"
" mov A, @R0 \n"
" rrc A \n"
" mov @R0, A \n"
" djnz DPH, 00007$ \n"
" pop _R0 \n"
//check on loop limit
" djnz DPL, 00088$ \n"
//we're done. undo the terrible things we've done to the stack
//first, get the result
" pop DPL \n"
" pop DPH \n"
" pop B \n"
" pop _R0 \n"
//now clear up the rest
" mov A, #-12 \n"
" add A, sp \n"
" mov sp, A \n"
" mov A, R0 \n"
//pop off regs
" pop _R0 \n"
" pop _R1 \n"
" pop _R2 \n"
" pop _R3 \n"
" ret \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves mathPrvDivMod16x8
static uint16_t mathPrvDivMod16x8(uint16_t num, uint8_t denom) __reentrant __naked
{
__asm__(
" push _R6 \n"
" push _R5 \n"
" push _R4 \n"
" push _R3 \n"
" push _R2 \n"
" push _R1 \n"
" push _R0 \n"
//get denom -> B
" mov A, #-9 \n"
" add A, sp \n"
" mov R0, A \n"
" mov B, @R0 \n"
//shift it off (in B), record how many iters we'll need (in R4), generate proper top 8 bits for result mask (in A)
" mov A, #1 \n"
" mov R4, #9 \n"
"00002$: \n"
" mov C, B.7 \n"
" jc 00003$ \n"
" rl A \n"
" xch A, B \n"
" rl A \n"
" xch A, B \n"
" inc R4 \n"
" sjmp 00002$ \n"
"00003$: \n"
//result mask in R3:R2 \n"
" mov R3, A \n"
" clr A \n"
" mov R2, A \n"
//quotient in R1:R0 \n"
" mov R1, B \n"
" mov R0, A \n"
//iter count in B \n"
" mov B, DPL \n"
//result in R6:R5
" mov R5, A \n"
" mov R6, A \n"
//loop-divide
"00088$: \n"
// check if denom.shifted >= num
" clr C \n"
" mov A, DPL \n"
" subb A, R0 \n"
" mov A, DPH \n"
" subb A, R1 \n"
" jc 00099$ \n" //no? skip this round
//subtract
" clr C \n"
" mov A, DPL \n"
" subb A, R0 \n"
" mov DPL, A \n"
" mov A, DPH \n"
" subb A, R1 \n"
" mov DPH, A \n"
//set bit in result
" mov A, R2 \n"
" orl A, R5 \n"
" mov R5, A \n"
" mov A, R3 \n"
" orl A, R6 \n"
" mov R6, A \n"
//set up next iteration
"00099$: \n"
// shift denom right one
" clr C \n"
" mov A, R1 \n"
" rrc A \n"
" mov R1, A \n"
" mov A, R0 \n"
" rrc A \n"
" mov R0, A \n"
// shift result mask right one
" clr C \n"
" mov A, R3 \n"
" rrc A \n"
" mov R3, A \n"
" mov A, R2 \n"
" rrc A \n"
" mov R2, A \n"
//check on loop limit
" djnz R4, 00088$ \n"
//we're done - produce the result (it is already in DPT Rif we want modulus)
" jb PSW.5, 00098$ \n"
" mov DPL, R5 \n"
" mov DPH, R6 \n"
"00098$: \n"
//pop off regs
" pop _R0 \n"
" pop _R1 \n"
" pop _R2 \n"
" pop _R3 \n"
" pop _R4 \n"
" pop _R5 \n"
" pop _R6 \n"
" ret \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves mathPrvDiv16x8
uint16_t mathPrvDiv16x8(uint16_t num, uint8_t denom) __reentrant __naked
{
__asm__(
" clr PSW.5 \n"
" ljmp _mathPrvDivMod16x8 \n"
);
(void)num;
(void)denom;
}
#pragma callee_saves mathPrvMod16x8
uint8_t mathPrvMod16x8(uint16_t num, uint8_t denom) __reentrant __naked
{
__asm__(
" setb PSW.5 \n"
" ljmp _mathPrvDivMod16x8 \n"
);
(void)num;
(void)denom;
}
char charsPrvDerefAndIncGenericPtr(const char * __xdata* __xdata str) __naked
{
__asm__(
" movx A, @DPTR \n"
" push A \n"
" add A, #1 \n"
" movx @DPTR, A \n"
" inc DPTR \n"
" movx A, @DPTR \n"
" push A \n"
" addc A, #0 \n"
" movx @DPTR, A \n"
" inc DPTR \n"
" movx A, @DPTR \n"
" pop _DPH \n"
" pop _DPL \n"
" jz 00001$ \n" //check for xdata, taken if yes
" cjne A, #0x60, 00002$ \n" //check for pdata, taken if no
//pdata
" push _R0 \n"
" mov R0, DPL \n"
" movx A, @R0 \n"
" pop _R0 \n"
" mov DPL, A \n"
" ret \n"
"00002$: \n"
" jc 00003$ \n" //check for idata. taken if yes
//code
" clr A \n"
" movc A, @A+DPTR \n"
" mov DPL, A \n"
" ret \n"
//xdata
"00001$: \n"
" movx A, @DPTR \n"
" mov DPL, A \n"
" ret \n"
//idata
"00003$: \n"
" push _R0 \n"
" mov R0, DPL \n"
" mov A, @R0 \n"
" pop _R0 \n"
" mov DPL, A \n"
" ret \n"
);
(void)str;
}
void mathPrvCopyPostinc(uint32_t __xdata *dst, uint32_t __xdata *src) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #4 \n" //repeat 4 times:
" setb C \n"
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" mov r2, a \n"
" addc a, #0 \n"
" movx @dptr, a \n"
" mov a, r2 \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx @dptr, a \n"
" inc dptr \n"
" djnz b, 00003$ \n"
" ljmp _u64_end \n"
);
(void)dst;
(void)src;
}
__bit xMemEqual4(const void __xdata* memA, const void __xdata* memB) __reentrant __naked
{
__asm__(
" lcall _u64_start \n" //get second pointer into R1:R0
" mov b, #4 \n" //repeat 4 times:
" clr C \n"
"00003$: \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" mov r2, a \n"
" inc dptr \n"
" lcall _mathPrvSwapDptrR1R0 \n"
" movx a, @dptr \n"
" inc dptr \n"
" xrl a, r2 \n"
" jnz 00004$ \n"
" djnz b, 00003$ \n"
" setb C \n"
"00004$: \n"
" ljmp _u64_end \n"
);
(void)memA;
(void)memB;
}
__bit u32minusU16(uint32_t __xdata *u32, uint16_t u16) __naked __reentrant
{
__asm__(
" lcall _u64_start \n"
" clr C \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" subb A, R0 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" subb A, R1 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" subb A, #0 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" subb A, #0 \n"
" ljmp _u64_end \n"
);
(void)u32;
(void)u16;
}
__bit u32plusU16(uint32_t __xdata *u32, uint16_t u16) __naked __reentrant
{
__asm__(
" lcall _u64_start \n"
" clr C \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" addc A, R0 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" addc A, R1 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" addc A, #0 \n"
" movx A, @DPTR \n"
" inc DPTR \n"
" addc A, #0 \n"
" ljmp _u64_end \n"
);
(void)u32;
(void)u16;
}
uint8_t u32Nonzero(uint32_t __xdata *u32) __naked __reentrant
{
__asm__(
" mov B, #4 \n"
"00001$: \n"
" movx A, @DPTR \n"
" jnz 00002$ \n"
" inc DPTR \n"
" djnz B, 00001$ \n"
"00002$: \n"
" mov DPL, A \n"
" ret \n"
);
(void)u32;
}
__bit i32Negative(uint32_t __xdata *u32) __naked __reentrant
{
__asm__(
" inc DPTR \n"
" inc DPTR \n"
" inc DPTR \n"
" movx A, @DPTR \n"
" rlc A \n"
" ret \n"
);
(void)u32;
}