author: kx <kx@radix-linux.su> 2024-12-20 16:11:07 +0300
committer: kx <kx@radix-linux.su> 2024-12-20 16:11:07 +0300
commit: 868b2b66b564b5c00e3a74d10be45db7151627ac
parent: cce2ae8d3312493b7653358bb4af201d3271377b
Commit Summary:
Diffstat:
1 file changed, 12717 insertions, 0 deletions
diff --git a/mpu/mpu-integer.c b/mpu/mpu-integer.c
new file mode 100644
index 0000000..5c7f670
--- /dev/null
+++ b/mpu/mpu-integer.c
@@ -0,0 +1,16254 @@
+
+/***************************************************************
+ __MPU_INTEGER.C
+
+ This file contains source code of functions for
+ INTEGER arithmetic operations.
+
+ PART OF : MPU - library .
+
+ USAGE : Internal only .
+
+ NOTE : NONE .
+
+ Copyright (C) 2000 - 2024 by Andrew V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h> /* errno(3) */
+#include <string.h> /* strcpy(3) */
+#include <strings.h> /* bzero(3) */
+
+#include <libmpu.h>
+#include <mpu-context.h>
+
+#include <mpu-emutype.h>
+#include <mpu-integer.h>
+
+#include <mpu-char.h>
+#include <mpu-symbols.h>
+
+#include <mpu-math-errno.h>
+#include <mpu-mtherr.h>
+
+/***************************************************************
+
+ Internal exploded integer-type data structure of a number
+ (a EMUSHORT is BITS_PER_EMUSHORT bits):
+
+ EMUSHORT ii[NP];
+
+ IF MPU_BYTE_ORDER_BIG_ENDIAN == 1 (m68k, PowerPC)
+
+ ii[0] - high EMUSHORT partion,
+ ii[NP-1] - low EMUSHORT partion.
+
+ - that is ---------------------------------------
+ pointer -> [high EMUSHORT partion] :0 part
+ [ . . . ] :1 part
+ .
+ .
+ .
+ [low EMUSHORT partion] :NP-1 part
+ -------------------------------------------------
+
+ ELSE IF MPU_BYTE_ORDER_BIG_ENDIAN == 0 (i386, Alpha)
+
+ ii[0] - low EMUSHORT partion.
+ ii[NP-1] - high EMUSHORT partion,
+
+ - that is ---------------------------------------
+ part 0: [low EMUSHORT partion] <- pointer
+ part 1: [ . . . ]
+ .
+ .
+ .
+ part NP-1: [high EMUSHORT partion]
+ -------------------------------------------------
+
+ ***************************************************************/
+
+
+/***************************************************************
+ Операции сложения и вычитания с учетом и без учета флага
+ переноса.
+ ***************************************************************/
+
+/***************************************************************
+ 8-bit operations:
+ */
+/* сложение знаковое и беззнаковое: */
+void iadd_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint16_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint16_t) (*a) & 0x0f) +
+ ((__mpu_uint16_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint16_t) (*a) +
+ (__mpu_uint16_t) (*b) + carry;
+ if( rc & 0x100 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint16_t) (*a);
+ op2 = (__mpu_uint16_t) (*b);
+ if( op1 & 0x80 ) op1 |= 0x100;
+ if( op2 & 0x80 ) op2 |= 0x100;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x100 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint8_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* сложение знаковое и беззнаковое с переносом: */
+void iadc_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint16_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint16_t) (*a) & 0x0f) +
+ ((__mpu_uint16_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint16_t) (*a) +
+ (__mpu_uint16_t) (*b) + carry;
+ if( rc & 0x100 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint16_t) (*a);
+ op2 = (__mpu_uint16_t) (*b);
+ if( op1 & 0x80 ) op1 |= 0x100;
+ if( op2 & 0x80 ) op2 |= 0x100;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x100 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint8_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое: */
+void isub_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint16_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint16_t) (*a) & 0x0f) -
+ ((__mpu_uint16_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint16_t) (*a) -
+ (__mpu_uint16_t) (*b) - carry;
+ if( rc & 0x100 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint16_t) (*a);
+ op2 = (__mpu_uint16_t) (*b);
+ if( op1 & 0x80 ) op1 |= 0x100;
+ if( op2 & 0x80 ) op2 |= 0x100;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint8_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое с переносом */
+void isbb_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint16_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint16_t) (*a) & 0x0f) -
+ ((__mpu_uint16_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint16_t) (*a) -
+ (__mpu_uint16_t) (*b) - carry;
+ if( rc & 0x100 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint16_t) (*a);
+ op2 = (__mpu_uint16_t) (*b);
+ if( op1 & 0x80 ) op1 |= 0x100;
+ if( op2 & 0x80 ) op2 |= 0x100;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint8_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/***************************************************************
+ 16-bit operations:
+ */
+/* сложение знаковое и беззнаковое: */
+void iadd_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint32_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint32_t) (*a) & 0x0f) +
+ ((__mpu_uint32_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint32_t) (*a) +
+ (__mpu_uint32_t) (*b) + carry;
+ if( rc & 0x10000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint32_t) (*a);
+ op2 = (__mpu_uint32_t) (*b);
+ if( op1 & 0x8000 ) op1 |= 0x10000;
+ if( op2 & 0x8000 ) op2 |= 0x10000;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x10000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x8000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint16_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* сложение знаковое и беззнаковое с переносом: */
+void iadc_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint32_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint32_t) (*a) & 0x0f) +
+ ((__mpu_uint32_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint32_t) (*a) +
+ (__mpu_uint32_t) (*b) + carry;
+ if( rc & 0x10000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint32_t) (*a);
+ op2 = (__mpu_uint32_t) (*b);
+ if( op1 & 0x8000 ) op1 |= 0x10000;
+ if( op2 & 0x8000 ) op2 |= 0x10000;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x10000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x8000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint16_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое: */
+void isub_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint32_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint32_t) (*a) & 0x0f) -
+ ((__mpu_uint32_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint32_t) (*a) -
+ (__mpu_uint32_t) (*b) - carry;
+ if( rc & 0x10000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint32_t) (*a);
+ op2 = (__mpu_uint32_t) (*b);
+ if( op1 & 0x8000 ) op1 |= 0x10000;
+ if( op2 & 0x8000 ) op2 |= 0x10000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x10000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x8000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint16_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое с переносом */
+void isbb_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint32_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint32_t) (*a) & 0x0f) -
+ ((__mpu_uint32_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint32_t) (*a) -
+ (__mpu_uint32_t) (*b) - carry;
+ if( rc & 0x10000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint32_t) (*a);
+ op2 = (__mpu_uint32_t) (*b);
+ if( op1 & 0x8000 ) op1 |= 0x10000;
+ if( op2 & 0x8000 ) op2 |= 0x10000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x10000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x8000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint16_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/***************************************************************
+ 32-bit operations:
+ */
+/* сложение знаковое и беззнаковое: */
+void iadd_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint64_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint64_t) (*a) & 0x0f) +
+ ((__mpu_uint64_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint64_t) (*a) +
+ (__mpu_uint64_t) (*b) + carry;
+ if( rc & 0x100000000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint64_t) (*a);
+ op2 = (__mpu_uint64_t) (*b);
+ if( op1 & 0x80000000 ) op1 |= 0x100000000;
+ if( op2 & 0x80000000 ) op2 |= 0x100000000;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x100000000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80000000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint32_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* сложение знаковое и беззнаковое с переносом: */
+void iadc_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint64_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint64_t) (*a) & 0x0f) +
+ ((__mpu_uint64_t) (*b) & 0x0f) + carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint64_t) (*a) +
+ (__mpu_uint64_t) (*b) + carry;
+ if( rc & 0x100000000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint64_t) (*a);
+ op2 = (__mpu_uint64_t) (*b);
+ if( op1 & 0x80000000 ) op1 |= 0x100000000;
+ if( op2 & 0x80000000 ) op2 |= 0x100000000;
+
+ rc = op1 + op2 + carry;
+ if( rc & 0x100000000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80000000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint32_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое: */
+void isub_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint64_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint64_t) (*a) & 0x0f) -
+ ((__mpu_uint64_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint64_t) (*a) -
+ (__mpu_uint64_t) (*b) - carry;
+ if( rc & 0x100000000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint64_t) (*a);
+ op2 = (__mpu_uint64_t) (*b);
+ if( op1 & 0x80000000 ) op1 |= 0x100000000;
+ if( op2 & 0x80000000 ) op2 |= 0x100000000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100000000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80000000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint32_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/* вычитание знаковое и беззнаковое с переносом */
+void isbb_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint64_t rc, op1, op2;
+ signed int carry, sign = 0;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ __CLEAR_IFLAGS;
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint64_t) (*a) & 0x0f) -
+ ((__mpu_uint64_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint64_t) (*a) -
+ (__mpu_uint64_t) (*b) - carry;
+ if( rc & 0x100000000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint64_t) (*a);
+ op2 = (__mpu_uint64_t) (*b);
+ if( op1 & 0x80000000 ) op1 |= 0x100000000;
+ if( op2 & 0x80000000 ) op2 |= 0x100000000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100000000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80000000 ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ *c = (__mpu_uint32_t) rc;
+ if( *c == 0 ) __STZ; /* set zero flag */
+}
+
+/***************************************************************
+ EMUSHORT (32-bit) operations:
+ */
+/* сложение знаковое и беззнаковое целых всех размеров */
+void iadd_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMULONG rc, op1, op2;
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iadd_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+ y = b + np - 1;
+ i = np - 1;
+#else
+ x = a;
+ y = b;
+ i = 0;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+#else
+ while( i < np - 1 )
+#endif
+ {
+ rc = (EMULONG) (*x) +
+ (EMULONG) (*y) + __MFLAG(CF);
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y; --i;
+#else
+ ++x; ++y; ++i;
+#endif
+ }
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set Carry Flag */
+ rc = (EMULONG) (*x) +
+ (EMULONG) (*y) + carry;
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (EMULONG) (*x);
+ op2 = (EMULONG) (*y);
+ if( op1 & MASK_SIGN ) op1 |= MASK_CARRY;
+ if( op2 & MASK_SIGN ) op2 |= MASK_CARRY;
+
+ rc = op1 + op2 + carry;
+ if( rc & MASK_CARRY ) carry = 1;
+ else carry = 0;
+ if( rc & MASK_SIGN ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+ zero ^= 1;
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+}
+
+/* сложение знаковое и беззнаковое целых всех размеров с переносом */
+void iadc_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMULONG rc, op1, op2;
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iadc_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+ y = b + np - 1;
+ i = np - 1;
+#else
+ x = a;
+ y = b;
+ i = 0;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+#else
+ while( i < np - 1 )
+#endif
+ {
+ rc = (EMULONG) (*x) +
+ (EMULONG) (*y) + __MFLAG(CF);
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y; --i;
+#else
+ ++x; ++y; ++i;
+#endif
+ }
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set Carry Flag */
+ rc = (EMULONG) (*x) +
+ (EMULONG) (*y) + carry;
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (EMULONG) (*x);
+ op2 = (EMULONG) (*y);
+ if( op1 & MASK_SIGN ) op1 |= MASK_CARRY;
+ if( op2 & MASK_SIGN ) op2 |= MASK_CARRY;
+
+ rc = op1 + op2 + carry;
+ if( rc & MASK_CARRY ) carry = 1;
+ else carry = 0;
+ if( rc & MASK_SIGN ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+ zero ^= 1;
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+}
+
+/* вычитание знаковое и беззнаковое целых всех размеров */
+void isub_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMULONG rc, op1, op2;
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isub_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+ y = b + np - 1;
+ i = np - 1;
+#else
+ x = a;
+ y = b;
+ i = 0;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+#else
+ while( i < np - 1 )
+#endif
+ {
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - __MFLAG(CF);
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y; --i;
+#else
+ ++x; ++y; ++i;
+#endif
+ }
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set Carry Flag */
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - carry;
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (EMULONG) (*x);
+ op2 = (EMULONG) (*y);
+ if( op1 & MASK_SIGN ) op1 |= MASK_CARRY;
+ if( op2 & MASK_SIGN ) op2 |= MASK_CARRY;
+
+ rc = op1 + op2 + carry;
+ if( rc & MASK_CARRY ) carry = 1;
+ else carry = 0;
+ if( rc & MASK_SIGN ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+ zero ^= 1;
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+}
+
+/* вычитание знаковое и беззнаковое целых всех размеров с переносом */
+void isbb_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMULONG rc, op1, op2;
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isbb_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+ y = b + np - 1;
+ i = np - 1;
+#else
+ x = a;
+ y = b;
+ i = 0;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+#else
+ while( i < np - 1 )
+#endif
+ {
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - __MFLAG(CF);
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y; --i;
+#else
+ ++x; ++y; ++i;
+#endif
+ }
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set Carry Flag */
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - carry;
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (EMULONG) (*x);
+ op2 = (EMULONG) (*y);
+ if( op1 & MASK_SIGN ) op1 |= MASK_CARRY;
+ if( op2 & MASK_SIGN ) op2 |= MASK_CARRY;
+
+ rc = op1 + op2 + carry;
+ if( rc & MASK_CARRY ) carry = 1;
+ else carry = 0;
+ if( rc & MASK_SIGN ) sign = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c[i] = (EMUSHORT) rc;
+ if( c[i] ) zero |= 1;
+ zero ^= 1;
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+}
+
+
+/***************************************************************
+ Операции сдвигов на 1 бит.
+ ***************************************************************/
+
+/***************************************************************
+ 8-bit operations:
+ */
+/* Логический беззнаковый сдвиг одного байта влево на один бит */
+void ishl_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x80 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический беззнаковый сдвиг одного байта вправо на один бит */
+void ishr_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x80; /* save sign */
+ if( save_sign ) __STO; /* set overflow flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( *c & 0x80 ) __STS; /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/* Арифметический сдвиг одного байта влево на один бит */
+void isal_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x80 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг одного байта вправо на один бит */
+void isar_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x80; /* save sign */
+ if( save_sign ) __STS; /* set sign flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ *c |= save_sign;
+
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/***************************************************************
+ 16-bit operations:
+ */
+/* Логический беззнаковый сдвиг двух байтов влево на один бит */
+void ishl_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x8000 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x8000 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический беззнаковый сдвиг двух байтов вправо на один бит */
+void ishr_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x8000; /* save sign */
+ if( save_sign ) __STO; /* set overflow flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( *c & 0x8000 ) __STS; /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/* Арифметический сдвиг двух байтов влево на один бит */
+void isal_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x8000 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x8000 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг двух байтов вправо на один бит */
+void isar_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x8000; /* save sign */
+ if( save_sign ) __STS; /* set sign flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ *c |= save_sign;
+
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/***************************************************************
+ 32-bit operations:
+ */
+/* Логический беззнаковый сдвиг четырех байтов влево на один бит */
+void ishl_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80000000 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x80000000 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический беззнаковый сдвиг четырех байтов вправо на один бит */
+void ishr_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x80000000; /* save sign */
+ if( save_sign ) __STO; /* set overflow flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( *c & 0x80000000 ) __STS; /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/* Арифметический сдвиг четырех байтов влево на один бит */
+void isal_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80000000 ) { carry = 1; __STC; } /* set carry flag */
+
+ *c = (*x) << 1;
+ if( *c == 0 ) __STZ; /* set zero flag */
+
+ if( *c & 0x80000000 ) { sign = 1; __STS; } /* set sign flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг четырех байтов вправо на один бит */
+void isar_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x, save_sign;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ save_sign = *x & 0x80000000; /* save sign */
+ if( save_sign ) __STS; /* set sign flag */
+
+ if( *x & 1 ) __STC; /* set carry flag */
+
+ *c = (*x) >> 1;
+ *c |= save_sign;
+
+ if( *c == 0 ) __STZ; /* set zero flag */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+/***************************************************************
+ EMUSHORT (32-bit) operations:
+ */
+/* Логический беззнаковый сдвиг влево на один бит */
+void ishl_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry, sign, zero = 1;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ishl_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#else
+ x = a; /* operand */
+ y = c; /* result */
+#endif
+
+ carry = 0;
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & MASK_SIGN ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) << 1;
+ *y |= __MFLAG(CF);
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический беззнаковый сдвиг вправо на один бит */
+void ishr_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y, save_sign;
+ signed int carry, zero = 1;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ishr_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a; /* operand */
+ y = c; /* result */
+#else
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#endif
+
+ carry = 0;
+
+ save_sign = *x & MASK_SIGN; /* save sign */
+ if( save_sign ) __STO; /* set overflow flag */
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & 1 ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) >> 1;
+ if( __MFLAG(CF) ) *y |= MASK_SIGN;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+}
+
+/* Арифметический сдвиг влево на один бит */
+void isal_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry, sign, zero = 1;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isal_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#else
+ x = a; /* operand */
+ y = c; /* result */
+#endif
+
+ carry = 0;
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & MASK_SIGN ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) << 1;
+ *y |= __MFLAG(CF);
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг вправо на один бит */
+void isar_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y, save_sign;
+ signed int carry, zero = 1;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isar_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a; /* operand */
+ y = c; /* result */
+#else
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#endif
+
+ carry = 0;
+
+ save_sign = *x & MASK_SIGN; /* save sign */
+ if( save_sign ) __STS; /* set sign flag */
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & 1 ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) >> 1;
+ if( __MFLAG(CF) ) *y |= MASK_SIGN;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( save_sign ) { *y |= save_sign; __CLZ; }
+}
+
+
+/***************************************************************
+ NOTE:
+ Операции iRCL... не изменяют флаг PF сохраняя его значение,
+ полученное после предыдущей операции. Флаг PF определяется
+ только для 8- и 16-битовых операций.
+
+ Операции iRCR... не изменяют флаг SF сохраняя его значение,
+ полученное после предыдущей операции.
+
+ Обе операции (iRCL... и iRCR...) выставляют флаг ZF по AND
+ с предыдущим значением:
+
+ newZF1 = newZF0 & lastZF,
+
+ где
+
+ & - oперация И (AND);
+ newZF1 - результирующий;
+ newZF0 - полученный в ходе операции над данным числом;
+ lastZF - бывший до проведения операции.
+
+ Данный способ вычисления значений флагов ZF, PF, SF
+ позволяет наиболее просто проводить сдвиги нескольких
+ операндов как единого целогою
+ ***************************************************************/
+
+/***************************************************************
+ Операции циклических сдвигов на 1 бит.
+ ***************************************************************/
+/***************************************************************
+ 8-bit operations:
+ */
+/* Циклический сдвиг одного байта влево на один бит */
+void irol_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80 ) __STC;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) { *c |= 1; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+
+ if( __MFLAG(SF) ) sign = 1;
+ if( __MFLAG(CF) ) carry = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта вправо на один бит */
+void iror_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int sign = 0, save_sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80 ) save_sign = 1; /* save sign */
+
+ if( *x & 1 ) __STC;
+
+ *c = (*x) >> 1;
+ if( __MFLAG(CF) ) { *c |= 0x80; __STS; }
+
+ if( *c == 0 ) __STZ;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( __MFLAG(SF) ) sign = 1;
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта влево на один бит с переносом */
+void ircl_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int carry = 0, sign = 0, zero = 0;
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x80 ) carry = 1;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) *c |= 0x01;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( *c & 0x80 ) { sign = 1; __STS; }
+
+ /* Не определяем parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта вправо на один бит с переносом */
+void ircr_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t *x;
+ signed int carry = 0, sign = 0, zero = 0, save_carry = 0;
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x80 ) sign = 1; /* save sign */
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ if( *x & 1 ) carry = 1;
+
+ *c = (*x) >> 1;
+ if( save_carry ) *c |= 0x80;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Не определяем sign flag */
+
+ if( (!save_carry && sign) || (save_carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/***************************************************************
+ 16-bit operations:
+ */
+/* Циклический сдвиг двух байтов влево на один бит */
+void irol_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x8000 ) __STC;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) { *c |= 1; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+
+ if( __MFLAG(SF) ) sign = 1;
+ if( __MFLAG(CF) ) carry = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов вправо на один бит */
+void iror_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int sign = 0, save_sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x8000 ) save_sign = 1; /* save sign */
+
+ if( *x & 1 ) __STC;
+
+ *c = (*x) >> 1;
+ if( __MFLAG(CF) ) { *c |= 0x8000; __STS; }
+
+ if( *c == 0 ) __STZ;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( __MFLAG(SF) ) sign = 1;
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов влево на один бит с переносом */
+void ircl_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int carry = 0, sign = 0, zero = 0;
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x8000 ) carry = 1;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) *c |= 0x0001;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( *c & 0x8000 ) { sign = 1; __STS; }
+
+ /* Не определяем parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов вправо на один бит с переносом */
+void ircr_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t *x;
+ signed int carry = 0, sign = 0, zero = 0, save_carry = 0;
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x8000 ) sign = 1; /* save sign */
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ if( *x & 1 ) carry = 1;
+
+ *c = (*x) >> 1;
+ if( save_carry ) *c |= 0x8000;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Не определяем sign flag */
+
+ if( (!save_carry && sign) || (save_carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/***************************************************************
+ 32-bit operations:
+ */
+/* Циклический сдвиг четырех байтов влево на один бит */
+void irol_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int carry = 0, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80000000 ) __STC;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) { *c |= 1; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+
+ if( __MFLAG(SF) ) sign = 1;
+ if( __MFLAG(CF) ) carry = 1;
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов вправо на один бит */
+void iror_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int sign = 0, save_sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ x = a;
+ if( *x & 0x80000000 ) save_sign = 1; /* save sign */
+
+ if( *x & 1 ) __STC;
+
+ *c = (*x) >> 1;
+ if( __MFLAG(CF) ) { *c |= 0x80000000; __STS; }
+
+ if( *c == 0 ) __STZ;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( __MFLAG(SF) ) sign = 1;
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов влево на один бит с переносом */
+void ircl_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int carry = 0, sign = 0, zero = 0;
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x80000000 ) carry = 1;
+
+ *c = (*x) << 1;
+ if( __MFLAG(CF) ) *c |= 0x00000001;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( *c & 0x80000000 ) { sign = 1; __STS; }
+
+ /* Не определяем parity flag */
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов вправо на один бит с переносом */
+void ircr_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t *x;
+ signed int carry = 0, sign = 0, zero = 0, save_carry = 0;
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ x = a; /* operand */
+ if( *x & 0x80000000 ) sign = 1; /* save sign */
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ if( *x & 1 ) carry = 1;
+
+ *c = (*x) >> 1;
+ if( save_carry ) *c |= 0x80000000;
+ if( *c ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Не определяем sign flag */
+
+ if( (!save_carry && sign) || (save_carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/***************************************************************
+ EMUSHORT (32-bit) operations:
+ */
+/* Циклический сдвиг влево на один бит */
+void irol_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 1;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"irol_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#else
+ x = a; /* operand */
+ y = c; /* result */
+#endif
+
+ carry = 0;
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & MASK_SIGN ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) << 1;
+ *y |= __MFLAG(CF);
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+ if( carry ) { *y |= 1; __CLZ; }
+
+ sign = __MFLAG(SF);
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг вправо на один бит */
+void iror_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry, zero = 1, sign = 0, save_sign = 0;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iror_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS_WITHOUT_CARRY;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a; /* operand */
+ y = c; /* result */
+#else
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#endif
+
+ carry = 0;
+
+ if( *x & MASK_SIGN ) save_sign = 1; /* save sign */
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & 1 ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) >> 1;
+ if( __MFLAG(CF) ) *y |= MASK_SIGN;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ ++i;
+ }
+
+ if( zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( carry ) { *y |= MASK_SIGN; __STS; __CLZ; }
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг влево на один бит с переносом */
+void ircl_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry = 0, sign = 0, zero = 1, save_zero = 0;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ircl_np (emushort)" );
+ return;
+ }
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ save_zero = __MFLAG(ZF);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#else
+ x = a; /* operand */
+ y = c; /* result */
+#endif
+
+ carry = __MFLAG(CF);
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & MASK_SIGN ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) << 1;
+ *y |= __MFLAG(CF);
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+ --y;
+#else
+ ++x;
+ ++y;
+#endif
+ ++i;
+ }
+
+ save_zero &= zero;
+
+ if( save_zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ /* Не определяем parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!carry && sign) || (carry && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг вправо на один бит с переносом */
+void ircr_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int carry, sign = 0, zero = 1, save_zero = 0, save_carry = 0;
+ signed int i = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ircr_np (emushort)" );
+ return;
+ }
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ save_zero = __MFLAG(ZF);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a; /* operand */
+ y = c; /* result */
+#else
+ x = a + np - 1; /* operand */
+ y = c + np - 1; /* result */
+#endif
+
+ carry = __MFLAG(CF);
+
+ if( *x & MASK_SIGN ) sign = 1; /* save sign */
+ if( carry ) save_carry = 1;
+
+ while( i < np )
+ {
+ if( carry ) __STC;
+ else __CLC;
+
+ if( *x & 1 ) carry = 1;
+ else carry = 0;
+
+ *y = (*x) >> 1;
+ if( __MFLAG(CF) ) *y |= MASK_SIGN;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ ++i;
+ }
+
+ save_zero &= zero;
+
+ if( save_zero ) { __STZ; } else { __CLZ; }
+ if( carry ) { __STC; } else { __CLC; }
+
+ /* Не определяем sign flag */
+
+ if( (!save_carry && sign) || (save_carry && !sign) ) __STO; /* set overflow flag */
+}
+
+
+/***************************************************************
+ POW_EMUSHORT (imply that the EMUSHORT size is 32 bits)
+ ***************************************************************/
+static EMUSHORT _POW_EMUSHORT( __mpu_int32_t x, __mpu_int32_t y )
+{
+ __mpu_int32_t z;
+ __mpu_int32_t n = y;
+
+ if( y < 0 ) n = -n;
+
+ for( z = 1; ; x *= x )
+ {
+ if( (n & 1) != 0 ) z *= x;
+ if( (n >>= 1) == 0 ) return( y < 0 ? (EMUSHORT)(1/z) : (EMUSHORT)z );
+ }
+}
+
+#define N_PARTS(b) ((b)>>POW2)
+#define N_BITS(b) ((b)&(BITS_PER_EMUSHORT-1))
+
+#define MASK_LEAST_BITS(b) (_POW_EMUSHORT(2,(b))-1)
+#define MASK_HIGEST_BITS(b) (~(_POW_EMUSHORT(2,(b))-1))
+
+
+/***************************************************************
+ Операции сдвигов на (b) бит.
+ ***************************************************************/
+
+/***************************************************************
+ 8-bit operations:
+ */
+/* Логический сдвиг одного байта влево на (b) бит */
+void ishln_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishln_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+ carry = (*c >> ((BITS_PER_BYTE-b)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический сдвиг одного байта вправо на (b) бит */
+void ishrn_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ signed int carry, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishrn_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) save_sign = 1; /* save_sign */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE ) /* обнуляем c */
+ {
+ *c = 0;
+
+ if( save_sign ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг одного байта влево на (b) бит */
+void isaln_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isaln_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+
+ carry = (*c >> ((BITS_PER_BYTE-b)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг одного байта вправо на (b) бит */
+void isarn_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ __mpu_uint8_t save_sign = 0;
+ signed int carry, sign;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isarn_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) { save_sign = 0xff; __STS; }
+ /* MASK_ALL_BITS == (-1) но при этом warning: convert type */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE ) /* выставляем флаги и уходим */
+ {
+ /* SF = SF */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE ) /* копируем знак c <= a */
+ {
+ *c = save_sign;
+
+ if( save_sign == 0 ) __STZ;
+
+ sign = __MFLAG(SF);
+ if( sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ sign = __MFLAG(SF);
+ if( sign ) /* копируем знак */
+ *c |= 0xff << (BITS_PER_BYTE-b);
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* SF (sign) уже установлен */
+ /* OF (overflow) уже сброшен в 0 */
+}
+
+
+/***************************************************************
+ 16-bit operations:
+ */
+#define BITS_PER_TWO_BYTES 16
+
+/* Логический сдвиг двух байтов влево на (b) бит */
+void ishln_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishln_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+ carry = (*c >> ((BITS_PER_TWO_BYTES-b)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический сдвиг двух байтов вправо на (b) бит */
+void ishrn_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ signed int carry, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishrn_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) save_sign = 1; /* save_sign */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES ) /* обнуляем c */
+ {
+ *c = 0;
+
+ if( save_sign ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг двух байтов влево на (b) бит */
+void isaln_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isaln_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+
+ carry = (*c >> ((BITS_PER_TWO_BYTES-b)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг двух байтов вправо на (b) бит */
+void isarn_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ __mpu_uint16_t save_sign = 0;
+ signed int carry, sign;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isarn_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) { save_sign = 0xffff; __STS; }
+ /* MASK_ALL_BITS == (-1) но при этом warning: convert type */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES ) /* выставляем флаги и уходим */
+ {
+ /* SF = SF */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES ) /* копируем знак c <= a */
+ {
+ *c = save_sign;
+
+ if( save_sign == 0 ) __STZ;
+
+ sign = __MFLAG(SF);
+ if( sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ sign = __MFLAG(SF);
+ if( sign ) /* копируем знак */
+ *c |= 0xffff << (BITS_PER_TWO_BYTES-b);
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* SF (sign) уже установлен */
+ /* OF (overflow) уже сброшен в 0 */
+}
+
+/***************************************************************
+ 32-bit operations:
+ */
+#define BITS_PER_FOUR_BYTES 32
+
+/* Логический сдвиг четырех байтов влево на (b) бит */
+void ishln_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishln_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+ carry = (*c >> ((BITS_PER_FOUR_BYTES-b)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Логический сдвиг четырех байтов вправо на (b) бит */
+void ishrn_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ signed int carry, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishrn_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) save_sign = 1; /* save_sign */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES ) /* обнуляем c */
+ {
+ *c = 0;
+
+ if( save_sign ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг четырех байтов влево на (b) бит */
+void isaln_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ signed int carry, sign, save_carry = 0, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isaln_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) save_sign = 1;
+ if( *a & 1 ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES )
+ {
+ *c = 0;
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+
+ carry = (*c >> ((BITS_PER_FOUR_BYTES-b)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c << b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Арифметический сдвиг четырех байтов вправо на (b) бит */
+void isarn_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ __mpu_uint32_t save_sign = 0;
+ signed int carry, sign;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isarn_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) { save_sign = 0xffffffff; __STS; }
+ /* MASK_ALL_BITS == (-1) но при этом warning: convert type */
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES ) /* выставляем флаги и уходим */
+ {
+ /* SF = SF */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES ) /* копируем знак c <= a */
+ {
+ *c = save_sign;
+
+ if( save_sign == 0 ) __STZ;
+
+ sign = __MFLAG(SF);
+ if( sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ *c = *c >> b;
+
+ sign = __MFLAG(SF);
+ if( sign ) /* копируем знак */
+ *c |= 0xffffffff << (BITS_PER_FOUR_BYTES-b);
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* SF (sign) уже установлен */
+ /* OF (overflow) уже сброшен в 0 */
+}
+
+/***************************************************************
+ EMUSHORT (32-bit) operations:
+ */
+/* Логический сдвиг влево на (b) бит */
+void ishln_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp;
+ signed int carry, save_carry = 0, sign, save_sign = 0, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ishln_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishln_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ if( *x & 1 ) save_carry = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ; /* set zero flag */
+
+ if( n_parts == np ) /* обнуляем c */
+ {
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = 0; ++y; --i; }
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS;
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + n_parts;
+ y = c + n_parts;
+#else
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x - 1) & 1 ) __STC;
+#else
+ if( *(x + 1) & 1 ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - n_parts) = *x;
+#else
+ *(y + n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ *y = 0;
+
+ zero &= 1;
+
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+
+ carry = BIT(y,(BITS_PER_EMUSHORT-n_bits));
+ if( carry ) __STC;
+ else __CLC;
+
+ *y = *y << n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y << n_bits;
+
+ tmp = tmp >> (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - 1) |= tmp;
+#else
+ *(y + 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* т.к. м.б. изменения */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Логический сдвиг вправо на (b) бит */
+void ishrn_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp;
+ signed int carry, save_sign = 0, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ishrn_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ishrn_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1; /* save_sign */
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ;
+
+ if( n_parts == np ) /* обнуляем c */
+ {
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = 0; ++y; --i; }
+
+ if( save_sign ) __STC;
+
+ __STZ; __CLS;
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#else
+ x = a + n_parts;
+ y = c + n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x + 1) & MASK_SIGN ) __STC;
+#else
+ if( *(x - 1) & MASK_SIGN ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + n_parts) = *x;
+#else
+ *(y - n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ --i;
+ }
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ *y = 0;
+
+ zero &= 1;
+
+ --i;
+ }
+
+ if( zero ) __STZ;
+ /* CF (carry) уже установлен */
+
+ if( save_sign ) __STO; /* set overflow flag */
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+
+ carry = BIT(y,(n_bits-1));
+ if( carry ) __STC;
+ else __CLC;
+
+ *y = *y >> n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y >> n_bits;
+
+ tmp = tmp << (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + 1) |= tmp;
+#else
+ *(y - 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y + 1) ) zero &= 0;
+#else
+ if( *(y - 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y + 1) ) zero &= 0;
+#else
+ if( *(y - 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+ if( save_sign ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Арифметический сдвиг влево на (b) бит */
+void isaln_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp;
+ signed int carry, sign, save_carry = 0, save_sign = 0, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isaln_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isaln_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ if( *x & 1 ) save_carry = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1; /* save_sign */
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ;
+
+ if( n_parts == np ) /* обнуляем c */
+ {
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = 0; ++y; --i; }
+
+ if( save_carry ) __STC;
+
+ __STZ; __CLS;
+
+ if( save_sign ) __STO; /* set overflow flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + n_parts;
+ y = c + n_parts;
+#else
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x - 1) & 1 ) __STC;
+#else
+ if( *(x + 1) & 1 ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - n_parts) = *x;
+#else
+ *(y + n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ *y = 0;
+
+ zero &= 1;
+
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+
+ carry = BIT(y,(BITS_PER_EMUSHORT-n_bits));
+ if( carry ) __STC;
+ else __CLC;
+
+ *y = *y << n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y << n_bits;
+
+ tmp = tmp >> (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - 1) |= tmp;
+#else
+ *(y + 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* т.к. м.б. изменения */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Арифметический сдвиг вправо на (b) бит */
+void isarn_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp, save_sign = 0;
+ signed int carry, sign, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isarn_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"isarn_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) { save_sign = MASK_ALL_BITS; __STS; }
+ /* MASK_ALL_BITS == (-1) но при этом warning: convert type */
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ /* SF = SF */
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ;
+
+ if( n_parts == np ) /* копируем знак c <= a */
+ {
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = save_sign; ++y; --i; }
+
+ if( save_sign == 0 ) __STZ;
+
+ sign = __MFLAG(SF);
+ if( sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#else
+ x = a + n_parts;
+ y = c + n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x + 1) & MASK_SIGN ) __STC;
+#else
+ if( *(x - 1) & MASK_SIGN ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + n_parts) = *x;
+#else
+ *(y - n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ --i;
+ }
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ *y = save_sign; /* копируем знак */
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+ /* SF (sign) уже установлен */
+ /* OF (overflow) уже сброшен */
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+
+ carry = BIT(y,(n_bits-1));
+ if( carry ) __STC;
+ else __CLC;
+
+ *y = *y >> n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y >> n_bits;
+
+ tmp = tmp << (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + 1) |= tmp;
+#else
+ *(y - 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y + 1) ) zero &= 0;
+#else
+ if( *(y - 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( __MFLAG(SF) ) /* копируем знак */
+ *y |= MASK_HIGEST_BITS((EMUSHORT)(BITS_PER_EMUSHORT-n_bits));
+
+ if( *(y) ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+ /* SF (sign) уже установлен */
+ /* OF (overflow) уже сброшен */
+
+ } /* End if( n_bits ) */
+
+}
+
+
+/***************************************************************
+ Операции циклических сдвигов на (b) бит.
+ ***************************************************************/
+
+/***************************************************************
+ 8-bit operations:
+ */
+/* Циклический сдвиг одного байта влево на (b) бит */
+void iroln_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ __mpu_uint8_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"iroln_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE )
+ {
+ if( *c & 1 ) __STC;
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+
+ carry = (*c >> ((BITS_PER_BYTE-b)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_BYTE-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x80 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта вправо на (b) бит */
+void irorn_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ __mpu_uint8_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"irorn_8" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_BYTE )
+ {
+ if( save_sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+
+ carry = (*c >> ((b-1)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_BYTE-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x80 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта влево на (b) бит с переносом */
+void ircln_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ __mpu_uint8_t tmp, save_carry = 0;
+ signed int carry, sign, save_sign = 0, zero = 0, save_parity;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircln_8" );
+ return;
+ }
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x80 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 0x80;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) zero &= 1;
+ else zero &= 0;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_BYTE ) __CLC;
+ if( b == BITS_PER_BYTE ) /* сдвиг на все */
+ {
+ save_parity = __MFLAG(PF);
+ ishr_8( c, c ); /* set CF */
+ if( save_parity ) { __STP; } else { __CLP; }
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ; __STS;
+
+ if( !save_sign ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+ carry = (*c >> ((BITS_PER_BYTE-b)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_BYTE-b);
+
+ tmp = tmp >> 1;
+ if( save_carry ) /* SET_BIT( &tmp, b-1 ); */
+ tmp |= ((__mpu_uint8_t)1 << ((b-1)&(BITS_PER_BYTE-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x80 ) __STS;
+ /* PF (parity) не определяем */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг одного байта вправо на (b) бит с переносом */
+void ircrn_8( __mpu_uint8_t *c, __mpu_uint8_t *a, unsigned int b )
+{
+ __mpu_uint8_t tmp, save_carry = 0;
+ signed int carry = 0, sign = 0, zero = 0, save_sign = 0;
+
+ if( b > BITS_PER_BYTE )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircrn_8" );
+ return;
+ }
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x80 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_BYTE )
+ {
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_BYTE ) __CLC;
+ if( b == BITS_PER_BYTE ) /* сдвиг на все */
+ {
+ sign = __MFLAG(SF);
+ ishl_8( c, c ); /* set CF */
+ if( sign ) __STS;
+ else __CLS;
+ sign = 0; /* return previous value*/
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c & 0x80 ) sign = 1;
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_BYTE ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_BYTE-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_BYTE-b);
+
+ tmp = tmp << 1;
+ if( save_carry ) /* SET_BIT( &tmp, BITS_PER_BYTE-b ); */
+ tmp |= ((__mpu_uint8_t)1 << ((BITS_PER_BYTE-b)&(BITS_PER_BYTE-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x80 ) sign = 1;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+}
+
+/***************************************************************
+ 16-bit operations:
+ */
+/* Циклический сдвиг двух байтов влево на (b) бит */
+void iroln_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ __mpu_uint16_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"iroln_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES )
+ {
+ if( *c & 1 ) __STC;
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+
+ carry = (*c >> ((BITS_PER_TWO_BYTES-b)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_TWO_BYTES-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов вправо на (b) бит */
+void irorn_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ __mpu_uint16_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"irorn_16" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x8000 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_TWO_BYTES )
+ {
+ if( save_sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+
+ carry = (*c >> ((b-1)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_TWO_BYTES-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов влево на (b) бит с переносом */
+void ircln_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ __mpu_uint16_t tmp, save_carry = 0;
+ signed int carry, sign, save_sign = 0, zero = 0, save_parity;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircln_16" );
+ return;
+ }
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x8000 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 0x8000;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) zero &= 1;
+ else zero &= 0;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_TWO_BYTES ) __CLC;
+ if( b == BITS_PER_TWO_BYTES ) /* сдвиг на все */
+ {
+ save_parity = __MFLAG(PF);
+ ishr_16( c, c ); /* set CF */
+ if( save_parity ) { __STP; } else { __CLP; }
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ; __STS;
+
+ if( !save_sign ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+ carry = (*c >> ((BITS_PER_TWO_BYTES-b)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_TWO_BYTES-b);
+
+ tmp = tmp >> 1;
+ if( save_carry ) /* SET_BIT( &tmp, b-1 ); */
+ tmp |= ((__mpu_uint16_t)1 << ((b-1)&(BITS_PER_TWO_BYTES-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x8000 ) __STS;
+ /* PF (parity) не определяем */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг двух байтов вправо на (b) бит с переносом */
+void ircrn_16( __mpu_uint16_t *c, __mpu_uint16_t *a, unsigned int b )
+{
+ __mpu_uint16_t tmp, save_carry = 0;
+ signed int carry = 0, sign = 0, zero = 0, save_sign = 0;
+
+ if( b > BITS_PER_TWO_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircrn_16" );
+ return;
+ }
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x8000 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_TWO_BYTES )
+ {
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_TWO_BYTES ) __CLC;
+ if( b == BITS_PER_TWO_BYTES ) /* сдвиг на все */
+ {
+ sign = __MFLAG(SF);
+ ishl_16( c, c ); /* set CF */
+ if( sign ) __STS;
+ else __CLS;
+ sign = 0; /* return previous value*/
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c & 0x8000 ) sign = 1;
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_TWO_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_TWO_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_TWO_BYTES-b);
+
+ tmp = tmp << 1;
+ if( save_carry ) /* SET_BIT( &tmp, BITS_PER_TWO_BYTES-b ); */
+ tmp |= ((__mpu_uint16_t)1 << ((BITS_PER_TWO_BYTES-b)&(BITS_PER_TWO_BYTES-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x8000 ) sign = 1;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+}
+
+/***************************************************************
+ 32-bit operations:
+ */
+/* Циклический сдвиг четырех байтов влево на (b) бит */
+void iroln_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ __mpu_uint32_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"iroln_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES )
+ {
+ if( *c & 1 ) __STC;
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+
+ carry = (*c >> ((BITS_PER_FOUR_BYTES-b)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_FOUR_BYTES-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов вправо на (b) бит */
+void irorn_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ __mpu_uint32_t tmp;
+ signed int carry, sign, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"irorn_32" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ if( *a & 0x80000000 ) save_sign = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) __STZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( b == BITS_PER_FOUR_BYTES )
+ {
+ if( save_sign ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+
+ carry = (*c >> ((b-1)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_FOUR_BYTES-b);
+ *c |= tmp;
+
+ if( *c == 0 ) __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов влево на (b) бит с переносом */
+void ircln_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ __mpu_uint32_t tmp, save_carry = 0;
+ signed int carry, sign, save_sign = 0, zero = 0, save_parity;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircln_32" );
+ return;
+ }
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x80000000 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 0x80000000;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES )
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ if( *c == 0 ) zero &= 1;
+ else zero &= 0;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_FOUR_BYTES ) __CLC;
+ if( b == BITS_PER_FOUR_BYTES ) /* сдвиг на все */
+ {
+ save_parity = __MFLAG(PF);
+ ishr_32( c, c ); /* set CF */
+ if( save_parity ) { __STP; } else { __CLP; }
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ; __STS;
+
+ if( !save_sign ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+ carry = (*c >> ((BITS_PER_FOUR_BYTES-b)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c << b;
+
+ tmp = tmp >> (BITS_PER_FOUR_BYTES-b);
+
+ tmp = tmp >> 1;
+ if( save_carry ) /* SET_BIT( &tmp, b-1 ); */
+ tmp |= ((__mpu_uint32_t)1 << ((b-1)&(BITS_PER_FOUR_BYTES-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x80000000 ) __STS;
+ /* PF (parity) не определяем */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+}
+
+/* Циклический сдвиг четырех байтов вправо на (b) бит с переносом */
+void ircrn_32( __mpu_uint32_t *c, __mpu_uint32_t *a, unsigned int b )
+{
+ __mpu_uint32_t tmp, save_carry = 0;
+ signed int carry = 0, sign = 0, zero = 0, save_sign = 0;
+
+ if( b > BITS_PER_FOUR_BYTES )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircrn_32" );
+ return;
+ }
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ zero = __MFLAG(ZF);
+
+ if( *a & 0x80000000 ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ *c = *a;
+
+ if( b == 0 || b == BITS_PER_FOUR_BYTES )
+ {
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( b != BITS_PER_FOUR_BYTES ) __CLC;
+ if( b == BITS_PER_FOUR_BYTES ) /* сдвиг на все */
+ {
+ sign = __MFLAG(SF);
+ ishl_32( c, c ); /* set CF */
+ if( sign ) __STS;
+ else __CLS;
+ sign = 0; /* return previous value*/
+
+ if( save_carry )
+ {
+ *c |= save_carry;
+
+ __CLZ;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c & 0x80000000 ) sign = 1;
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || b == BITS_PER_FOUR_BYTES ) */
+
+ carry = (*c >> ((b-1)&(BITS_PER_FOUR_BYTES-1)))&1;
+ if( carry ) __STC;
+ else __CLC;
+
+ tmp = *c;
+ *c = *c >> b;
+
+ tmp = tmp << (BITS_PER_FOUR_BYTES-b);
+
+ tmp = tmp << 1;
+ if( save_carry ) /* SET_BIT( &tmp, BITS_PER_FOUR_BYTES-b ); */
+ tmp |= ((__mpu_uint32_t)1 << ((BITS_PER_FOUR_BYTES-b)&(BITS_PER_FOUR_BYTES-1)));
+
+ *c |= tmp;
+
+ if( *c ) zero &= 0;
+ else zero &= 1;
+ if( zero ) { __STZ; } else { __CLZ; }
+
+ if( *c & 0x80000000 ) sign = 1;
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+}
+
+/***************************************************************
+ EMUSHORT (32-bit) operations:
+ */
+/* Циклический сдвиг влево на (b) бит */
+void iroln_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp, temp, *ptemp = 0;
+ signed int carry, sign, save_sign = 0, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iroln_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"iroln_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1; /* save_sign */
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS;
+ else __CLS;
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ if( n_parts == np )
+ {
+ if( *y & 1 ) __STC;
+ else __CLC;
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+ /* save shifting (put out) parts *************************/
+ ptemp = (EMUSHORT *)__mpu_sbrk( (int)(n_parts*SIZE_OF_EMUSHORT) );
+ if( !ptemp )
+ {
+ /* fatal error */
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np - 1;
+#endif
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ptemp[n_parts-i] = *x;
+#else
+ ptemp[i-1] = *x;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x;
+#else
+ --x;
+#endif
+ --i;
+ }
+ /*********************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + n_parts;
+ y = c + n_parts;
+#else
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x - 1) & 1 ) __STC;
+#else
+ if( *(x + 1) & 1 ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - n_parts) = *x;
+#else
+ *(y + n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+
+ i = 0;
+ while( i < n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y; *y = ptemp[n_parts-1-i];
+#else
+ ++y; *y = ptemp[i];
+#endif
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ ++i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+
+ /* FREE ptemp *************/
+ __mpu_sbrk( -(int)(n_parts*SIZE_OF_EMUSHORT) );
+ /**************************/
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+
+ carry = BIT(y,(BITS_PER_EMUSHORT-n_bits));
+ if( carry ) __STC;
+ else __CLC;
+
+ /* save shifting (put out) bits *****************/
+ temp = *y;
+ temp = temp >> (BITS_PER_EMUSHORT-n_bits);
+ /************************************************/
+
+ *y = *y << n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y << n_bits;
+
+ tmp = tmp >> (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - 1) |= tmp;
+#else
+ *(y + 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ /* copy shifting bits */
+ *y |= temp;
+ /**********************/
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* т.к. м.б. изменения */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Циклический сдвиг вправо на (b) бит */
+void irorn_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp, temp, *ptemp = 0;
+ signed int carry, sign, save_sign = 0, zero = 1;
+ signed int i, n_parts, n_bits;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"irorn_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"irorn_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS;
+ else __CLS;
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+ if( n_parts == np )
+ {
+ if( save_sign ) __STC;
+ else __CLC;
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+ /* save shifting (put out) parts *************************/
+ ptemp = (EMUSHORT *)__mpu_sbrk( (int)(n_parts*SIZE_OF_EMUSHORT) );
+ if( !ptemp )
+ {
+ /* fatal error */
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+
+ i = 0;
+ while( i < n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ptemp[n_parts-1-i] = *x;
+#else
+ ptemp[i] = *x;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ ++i;
+ }
+ /*********************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#else
+ x = a + n_parts;
+ y = c + n_parts;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(x + 1) & MASK_SIGN ) __STC;
+#else
+ if( *(x - 1) & MASK_SIGN ) __STC;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + n_parts) = *x;
+#else
+ *(y - n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ --i;
+ }
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y; *y = ptemp[n_parts-i];
+#else
+ --y; *y = ptemp[i-1];
+#endif
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO; /* set overflow flag */
+
+ /* FREE ptemp *************/
+ __mpu_sbrk( -(int)(n_parts*SIZE_OF_EMUSHORT) );
+ /**************************/
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+
+ carry = BIT(y,(n_bits-1));
+ if( carry ) __STC;
+ else __CLC;
+
+ /* save shifting (put out) bits *****************/
+ temp = *y;
+ temp = temp << (BITS_PER_EMUSHORT-n_bits);
+ /************************************************/
+
+ *y = *y >> n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y >> n_bits;
+
+ tmp = tmp << (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + 1) |= tmp;
+#else
+ *(y - 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y + 1) ) zero &= 0;
+#else
+ if( *(y - 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+
+ /* copy shifting bits */
+ *y |= temp;
+ /**********************/
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ if( zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* т.к. м.б. изменения */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Циклический сдвиг влево на (b) бит с переносом */
+void ircln_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp, temp, *ptemp = 0, save_carry = 0;
+ signed int carry, sign, save_sign = 0, zero = 1, save_zero = 0, save_parity;
+ signed int save_part_carry = 0;
+ signed int i, n_parts, n_bits;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ircln_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircln_np (emushort)" );
+ return;
+ }
+
+ /* Оставляем CF, PF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLS; __CLV;
+
+ save_zero = __MFLAG(ZF);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = MASK_SIGN;
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ if( save_sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( n_parts != np ) __CLC;
+ if( n_parts == np ) /* сдвиг на все */
+ {
+ save_parity = __MFLAG(PF);
+ ishr_np( c, c, np ); /* set CF */
+ if( save_parity ) __STP;
+ else __CLP;
+
+ if( save_carry )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ *y |= save_carry;
+
+ __CLZ; __STS;
+
+ if( !save_sign ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+ /* save shifting (put out) parts *************************/
+ ptemp = (EMUSHORT *)__mpu_sbrk( (int)(n_parts*SIZE_OF_EMUSHORT) );
+ if( !ptemp )
+ {
+ /* fatal error */
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np - 1;
+#endif
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ptemp[n_parts-i] = *x;
+#else
+ ptemp[i-1] = *x;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x;
+#else
+ --x;
+#endif
+ --i;
+ }
+ /*********************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + n_parts;
+ y = c + n_parts;
+#else
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - n_parts) = *x;
+#else
+ *(y + n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+
+ /* save carry ***************************/
+ save_parity = __MFLAG(PF);
+ ishr_np( ptemp, ptemp, n_parts ); /* set CF */
+ if( save_parity ) __STP;
+ else __CLP;
+ /* Эта операция установит правильный CF */
+
+ i = 0;
+ while( i < n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y; *y = ptemp[n_parts-1-i];
+#else
+ ++y; *y = ptemp[i];
+#endif
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ ++i;
+ }
+
+ /* copy old carry (CF) *****/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - n_parts;
+#else
+ y = c + n_parts - 1;
+#endif
+ *y |= save_carry;
+ if( save_carry ) zero &= 0;
+ else zero &= 1;
+ /***************************/
+
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* м.б. изменения (SHR) */
+
+ /* PF (parity) не определяем */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ /* FREE ptemp *************/
+ __mpu_sbrk( -(int)(n_parts*SIZE_OF_EMUSHORT) );
+ /**************************/
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+
+ carry = __MFLAG(CF);
+
+ if( n_parts == 0 )
+ {
+ if( carry ) save_carry = 1;
+ }
+
+ if( n_parts )
+ {
+ if( carry ) save_part_carry = 1;
+ }
+
+ carry = BIT(y,(BITS_PER_EMUSHORT-n_bits));
+ if( carry ) __STC;
+ else __CLC;
+
+ /* save shifting (put out) bits *****************/
+ temp = *y;
+ temp = temp >> (BITS_PER_EMUSHORT-n_bits);
+ /************************************************/
+
+ *y = *y << n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+#else
+ --y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y << n_bits;
+
+ tmp = tmp >> (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y - 1) |= tmp;
+#else
+ *(y + 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y - 1) ) zero &= 0;
+#else
+ if( *(y + 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ /* copy shifting bits */
+ if( n_parts == 0 )
+ {
+ temp = temp >> 1;
+ if( save_carry ) SET_BIT( &temp, n_bits-1 );
+ }
+ if( n_parts )
+ {
+ temp = temp >> 1; /* только для RCR, RCL */
+ if( save_part_carry )
+ SET_BIT( &temp, n_bits-1 );
+ }
+ *y |= temp;
+ /**********************/
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ save_zero = __MFLAG(ZF);
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+ else __CLS; /* т.к. м.б. изменения */
+
+ /* PF (parity) не определяем */
+
+ sign = __MFLAG(SF);
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+/* Циклический сдвиг вправо на (b) бит с переносом */
+void ircrn_np( EMUSHORT *c, EMUSHORT *a, unsigned int b, int np )
+{
+ EMUSHORT *x, *y, tmp, temp, *ptemp = 0, save_carry = 0;
+ signed int carry, sign = 0, save_sign = 0, zero = 1, save_zero;
+ signed int save_part_carry = 0;
+ signed int i, n_parts, n_bits;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ircrn_np (emushort)" );
+ return;
+ }
+
+ if( b > BITS_PER_EMUSHORT * np )
+ {
+ /* error: Invalid number of shifts */
+ __integer_invalid_shift( (__mpu_char8_t *)"ircrn_np (emushort)" );
+ return;
+ }
+
+ /* Оставляем CF, SF, ZF; остальные сбрасываем: */
+ __CLA; __CLO; __CLP; __CLV;
+
+ save_zero = __MFLAG(ZF);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+ y = c;
+#else
+ x = a + np - 1;
+ y = c + np - 1;
+#endif
+
+ if( *x & MASK_SIGN ) save_sign = 1;
+ if( __MFLAG(CF) ) save_carry = 1;
+
+ n_parts = N_PARTS(b);
+
+ if( b == 0 || n_parts == np ) /* выставляем флаги и уходим */
+ {
+ i = np;
+ while( i > 0 )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x; ++y;
+#else
+ --x; --y;
+#endif
+ --i;
+ }
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+
+ /* Если сдвиг на все, то не трогаем CF (carry) */
+ if( n_parts != np ) __CLC;
+ if( n_parts == np ) /* сдвиг на все */
+ {
+ sign = __MFLAG(SF);
+ ishl_np( c, c, np ); /* set CF */
+ if( sign ) __STS;
+ else __CLS;
+ sign = 0; /* return previous value*/
+
+ if( save_carry )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+ *y |= save_carry;
+
+ __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) sign = 1;
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+ }
+ }
+
+ return;
+
+ } /* End if( b == 0 || n_parts == np ) */
+
+ n_bits = N_BITS(b);
+
+ if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
+ {
+ x = a;
+ y = c;
+
+ i = np;
+ while( i > 0 ) { *y = *x; ++x; ++y; --i; }
+ }
+
+ if( n_parts )
+ {
+ /* save shifting (put out) parts *************************/
+ ptemp = (EMUSHORT *)__mpu_sbrk( (int)(n_parts*SIZE_OF_EMUSHORT) );
+ if( !ptemp )
+ {
+ /* fatal error */
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+
+ i = 0;
+ while( i < n_parts )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ptemp[n_parts-1-i] = *x;
+#else
+ ptemp[i] = *x;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ ++i;
+ }
+ /*********************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1 - n_parts;
+ y = c + np - 1 - n_parts;
+#else
+ x = a + n_parts;
+ y = c + n_parts;
+#endif
+
+ i = np - n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + n_parts) = *x;
+#else
+ *(y - n_parts) = *x;
+#endif
+
+ if( *x ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ --i;
+ }
+
+ /* save carry ***************************/
+ save_sign = __MFLAG(SF);
+ ishl_np( ptemp, ptemp, n_parts );
+ if( save_sign ) __STS;
+ else __CLS;
+ /* Эта операция установит правильный CF */
+
+ i = n_parts;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y; *y = ptemp[n_parts-i];
+#else
+ --y; *y = ptemp[i-1];
+#endif
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ --i;
+ }
+
+ /* copy old carry (CF) *****/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + n_parts - 1;
+#else
+ y = c + np - n_parts;
+#endif
+ *y |= save_carry;
+ if( save_carry ) zero &= 0;
+ else zero &= 1;
+ /***************************/
+
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) sign = 1; /* SF не устанавливаем */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ /* FREE ptemp *************/
+ __mpu_sbrk( -(int)(n_parts*SIZE_OF_EMUSHORT) );
+ /**************************/
+
+ } /* End if( n_parts ) */
+
+ if( n_bits )
+ {
+ zero = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c + np - 1;
+#else
+ y = c;
+#endif
+
+ carry = __MFLAG(CF);
+
+ if( n_parts == 0 )
+ {
+ if( carry ) save_carry = 1;
+ }
+
+ if( n_parts )
+ {
+ if( carry ) save_part_carry = 1;
+ }
+
+ carry = BIT(y,(n_bits-1));
+ if( carry ) __STC;
+ else __CLC;
+
+ /* save shifting (put out) bits *****************/
+ temp = *y;
+ temp = temp << (BITS_PER_EMUSHORT-n_bits);
+ /************************************************/
+
+ *y = *y >> n_bits;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+
+ i = np - 1;
+ while( i > 0 )
+ {
+ tmp = *y;
+ *y = *y >> n_bits;
+
+ tmp = tmp << (BITS_PER_EMUSHORT-n_bits);
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(y + 1) |= tmp;
+#else
+ *(y - 1) |= tmp;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(y + 1) ) zero &= 0;
+#else
+ if( *(y - 1) ) zero &= 0;
+#endif
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --y;
+#else
+ ++y;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+
+ /* copy shifting bits */
+ if( n_parts == 0 )
+ {
+ temp = temp << 1;
+ if( save_carry )
+ SET_BIT( &temp, BITS_PER_EMUSHORT-n_bits );
+ }
+
+ if( n_parts )
+ {
+ temp = temp << 1; /* только для RCR, RCL */
+ if( save_part_carry )
+ SET_BIT( &temp, BITS_PER_EMUSHORT-n_bits );
+ }
+ *y |= temp;
+ /**********************/
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+ save_zero &= zero;
+ if( save_zero ) __STZ;
+ else __CLZ;
+ /* CF (carry) уже установлен */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = c;
+#else
+ y = c + np - 1;
+#endif
+ if( *y & MASK_SIGN ) sign = 1;
+ else sign = 0; /* т.к. м.б. изменения */
+
+ if( (!save_sign && sign) || (save_sign && !sign) ) __STO;
+ else __CLO;
+
+ } /* End if( n_bits ) */
+
+}
+
+
+/***************************************************************
+ Операция NOT [c = (инверсия всех разрядов)a].
+ (поразрядное логическое НЕ).
+ На флаги не воздействует.
+ ***************************************************************/
+
+void inot_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ *c = ~(*a);
+}
+
+void inot_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ *c = ~(*a);
+}
+
+void inot_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ *c = ~(*a);
+}
+
+void inot_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x, *y;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"inot_np (emushort)" );
+ return;
+ }
+
+ x = a; y = c;
+
+ i = np;
+ while( i > 0 )
+ {
+ *y = ~(*x);
+ ++x; ++y; --i;
+ }
+}
+
+
+/***************************************************************
+ Операция NEG [c = - a].
+ Воздействует на флаги: AF, CF, OF, PF, SF, ZF.
+ ***************************************************************/
+
+void ineg_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t inc = 1;
+
+ inot_8( c, a );
+ iadd_8( c, c, &inc ); /* Set Flags */
+}
+
+void ineg_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t inc = 1;
+
+ inot_16( c, a );
+ iadd_16( c, c, &inc ); /* Set Flags */
+}
+
+void ineg_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t inc = 1;
+
+ inot_32( c, a );
+ iadd_32( c, c, &inc ); /* Set Flags */
+}
+
+void ineg_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *inc = (EMUSHORT *)EMUSHORT_C( 0 );
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ineg_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory and *inc = 1; *****************************/
+ inc = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !inc )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)inc, 0, np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(inc + np - 1) = (EMUSHORT) 1;
+#else
+ *inc = (EMUSHORT) 1;
+#endif
+ /*************************************************************/
+
+ inot_np( c, a, np );
+ iadd_np( c, c, inc, np ); /* Set Flags */
+
+ /* FREE inc **********/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*********************/
+}
+
+
+/***************************************************************
+ Операция AND [c = a <AND> b].
+ (поразрядное логическое И).
+ Воздействует на флаги: AF=(undefined), CF=0, OF=0, PF, SF, ZF.
+ ***************************************************************/
+
+void iand_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a & *b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+void iand_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a & *b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+void iand_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a & *b;
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+}
+
+void iand_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMUSHORT *x, *y;
+ signed int zero = 1;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iand_np (emushort)" );
+ return;
+ }
+
+ /* AF (aux_carry) = 0; Не определяем. */
+ /* PF (parity) = 0; Не определяем (для операций > 16-bit). */
+ __CLEAR_IFLAGS;
+
+ x = a;
+ y = b;
+
+ i = 0;
+
+ c[i] = *x & *y;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+
+ while( i < np )
+ {
+ c[i] = *x & *y;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y;
+ ++i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+ --i;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+}
+
+
+/***************************************************************
+ Операция TEST [a <TEST> b]. Не изменяет значения операндов.
+ (поразрядное логическое И).
+ Воздействует на флаги: AF=(undefined), CF=0, OF=0, PF, SF, ZF.
+ ***************************************************************/
+
+void itest_8( __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint8_t c;
+
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ c = *a & *b;
+
+ if( c == 0 ) __STZ;
+ if( c & 0x80 ) __STS;
+
+ if( __MPARITY(c) ) __STP; /* set parity flag */
+}
+
+void itest_16( __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint16_t c;
+
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ c = *a & *b;
+
+ if( c == 0 ) __STZ;
+ if( c & 0x8000 ) __STS;
+
+ if( __MPARITY(c) ) __STP; /* set parity flag */
+}
+
+void itest_32( __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint32_t c;
+
+ /* AF (aux_carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ c = *a & *b;
+
+ if( c == 0 ) __STZ;
+ if( c & 0x80000000 ) __STS;
+
+ if( __MPARITY(c) ) __STP; /* set parity flag */
+}
+
+void itest_np( EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMUSHORT *x, *y, c;
+ signed int zero = 1;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"itest_np (emushort)" );
+ return;
+ }
+
+ /* AF (aux_carry) = 0; Не определяем. */
+ /* PF (parity) = 0; Не определяем (для операций > 16-bit). */
+ __CLEAR_IFLAGS;
+
+ x = a;
+ y = b;
+
+ i = 0;
+
+ c = *x & *y;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( c & MASK_SIGN ) __STS;
+#endif
+
+ if( c ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+
+ while( i < np )
+ {
+ c = *x & *y;
+
+ if( c ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y;
+ ++i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ if( c & MASK_SIGN ) __STS;
+#endif
+}
+
+
+/***************************************************************
+ Операция сравнения CMP. [фактически <a - b>].
+ Не изменяет значения операндов.
+ Выставляет флаги: AF, CF, OF, SF, PF, ZF.
+ ***************************************************************/
+
+/* Сравнение операндов размером в байт */
+void icmp_8( __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint16_t rc, op1, op2;
+ __mpu_uint8_t c;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint16_t) (*a) & 0x0f) -
+ ((__mpu_uint16_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint16_t) (*a) -
+ (__mpu_uint16_t) (*b) - carry;
+ if( rc & 0x100 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint16_t) (*a);
+ op2 = (__mpu_uint16_t) (*b);
+ if( op1 & 0x80 ) op1 |= 0x100;
+ if( op2 & 0x80 ) op2 |= 0x100;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80 ) sign = 1;
+
+ if((!carry && sign) || (carry && !sign)) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c = (__mpu_uint8_t) rc;
+ if( c == 0 ) __STZ; /* set zero flag */
+}
+
+/* Сравнение операндов размером в два байта */
+void icmp_16( __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint32_t rc, op1, op2;
+ __mpu_uint16_t c;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint32_t) (*a) & 0x0f) -
+ ((__mpu_uint32_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint32_t) (*a) -
+ (__mpu_uint32_t) (*b) - carry;
+ if( rc & 0x10000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ if( __MPARITY(rc) ) __STP; /* set parity flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint32_t) (*a);
+ op2 = (__mpu_uint32_t) (*b);
+ if( op1 & 0x8000 ) op1 |= 0x10000;
+ if( op2 & 0x8000 ) op2 |= 0x10000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x10000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x8000 ) sign = 1;
+
+ if((!carry && sign) || (carry && !sign)) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c = (__mpu_uint16_t) rc;
+ if( c == 0 ) __STZ; /* set zero flag */
+}
+
+/* Сравнение операндов размером в четыре байта */
+void icmp_32( __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint64_t rc, op1, op2;
+ __mpu_uint32_t c;
+ signed int carry, sign = 0;
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set auxiliary carry flag */
+ rc = ((__mpu_uint64_t) (*a) & 0x0f) -
+ ((__mpu_uint64_t) (*b) & 0x0f) - carry;
+ if( rc & 0x10 ) __STA; /* set aux carry flag */
+
+ /* set carry flag */
+ rc = (__mpu_uint64_t) (*a) -
+ (__mpu_uint64_t) (*b) - carry;
+ if( rc & 0x100000000 ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (__mpu_uint64_t) (*a);
+ op2 = (__mpu_uint64_t) (*b);
+ if( op1 & 0x80000000 ) op1 |= 0x100000000;
+ if( op2 & 0x80000000 ) op2 |= 0x100000000;
+
+ rc = op1 - op2 - carry;
+ if( rc & 0x100000000 ) carry = 1;
+ else carry = 0;
+ if( rc & 0x80000000 ) sign = 1;
+
+ if((!carry && sign) || (carry && !sign)) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c = (__mpu_uint32_t) rc;
+ if( c == 0 ) __STZ; /* set zero flag */
+}
+
+/* Сравнение целых операндов всех размеров */
+void icmp_np( EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMULONG rc, op1, op2;
+ EMUSHORT *x, *y;
+ EMUSHORT c;
+ signed int carry, sign = 0, zero = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icmp_np (emushort)" );
+ return;
+ }
+
+ __CLEAR_IFLAGS;
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+ y = b + np - 1;
+ i = np - 1;
+#else
+ x = a;
+ y = b;
+ i = 0;
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+#else
+ while( i < np - 1 )
+#endif
+ {
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - __MFLAG(CF);
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+ c = (EMUSHORT) rc;
+ if( c ) zero |= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y; --i;
+#else
+ ++x; ++y; ++i;
+#endif
+ }
+
+ carry = __MFLAG(CF); /* save carry flag */
+
+ /* set Carry Flag */
+ rc = (EMULONG) (*x) -
+ (EMULONG) (*y) - carry;
+ if( rc & MASK_CARRY ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* copy sign bit */
+ op1 = (EMULONG) (*x);
+ op2 = (EMULONG) (*y);
+ if( op1 & MASK_SIGN ) op1 |= MASK_CARRY;
+ if( op2 & MASK_SIGN ) op2 |= MASK_CARRY;
+
+ rc = op1 - op2 - carry;
+ if( rc & MASK_CARRY ) carry = 1;
+ else carry = 0;
+ if( rc & MASK_SIGN ) sign = 1;
+
+ if((!carry && sign) || (carry && !sign)) __STO; /* set overflow flag */
+ if( sign ) __STS; /* set sign flag */
+ else __CLS; /* clear sign flag */
+
+ c = (EMUSHORT) rc;
+ if( c ) zero |= 1;
+ zero ^= 1;
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+}
+
+
+/***************************************************************
+ Операция OR [c = a <OR> b].
+ (поразрядное логическое ИЛИ).
+ Воздействует на флаги: AF=(undefined), CF=0, OF=0, PF, SF, ZF.
+ ***************************************************************/
+
+void ior_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a | *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+}
+
+void ior_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a | *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+}
+
+void ior_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a | *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+}
+
+void ior_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMUSHORT *x, *y;
+ signed int zero = 1;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ior_np (emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = a;
+ y = b;
+
+ i = 0;
+
+ c[i] = *x | *y;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+
+ while( i < np )
+ {
+ c[i] = *x | *y;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+ }
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+
+ --i;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+}
+
+
+/***************************************************************
+ Операция XOR [c = a <XOR> b].
+ (поразрядное логическое исключающее ИЛИ).
+ Воздействует на флаги: AF=(undefined), CF=0, OF=0, PF, SF, ZF.
+ ***************************************************************/
+
+void ixor_8( __mpu_uint8_t *c, __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a ^ *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+}
+
+void ixor_16( __mpu_uint16_t *c, __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a ^ *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+}
+
+void ixor_32( __mpu_uint32_t *c, __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a ^ *b;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+}
+
+void ixor_np( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMUSHORT *x, *y;
+ signed int zero = 1;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ior_np (emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = a;
+ y = b;
+
+ i = 0;
+
+ c[i] = *x ^ *y;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+
+ while( i < np )
+ {
+ c[i] = *x ^ *y;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++y; ++i;
+ }
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+
+ --i;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+}
+
+
+/***************************************************************
+ Операция INC (инкремент) [c = a + 1].
+ Воздействует на флаги: AF, OF, PF, SF, ZF.
+ Флаг CF не изменяется.
+ ***************************************************************/
+
+void iinc_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t inc = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ iadd_8( c, a, &inc ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void iinc_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t inc = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ iadd_16( c, a, &inc ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void iinc_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t inc = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ iadd_32( c, a, &inc ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void iinc_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *inc = (EMUSHORT *)EMUSHORT_C( 0 );
+ signed int save_carry;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iinc_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory and *inc = 1; *****************************/
+ inc = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !inc )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)inc, 0, np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(inc + np - 1) = (EMUSHORT) 1;
+#else
+ *inc = (EMUSHORT) 1;
+#endif
+ /*************************************************************/
+
+ save_carry = __MFLAG(CF);
+ iadd_np( c, a, inc, np ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* FREE inc **********/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*********************/
+}
+
+
+/***************************************************************
+ Операция DEC (декремент) [c = a - 1].
+ Воздействует на флаги: AF, OF, PF, SF, ZF.
+ Флаг CF не изменяется.
+ ***************************************************************/
+
+void idec_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t dec = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ isub_8( c, a, &dec ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void idec_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t dec = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ isub_16( c, a, &dec ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void idec_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t dec = 1;
+ signed int save_carry;
+
+ save_carry = __MFLAG(CF);
+ isub_32( c, a, &dec ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+}
+
+void idec_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *dec = (EMUSHORT *)EMUSHORT_C( 0 );
+ signed int save_carry;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"idec_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory and *inc = 1; *****************************/
+ dec = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !dec )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)dec, 0, np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(dec + np - 1) = (EMUSHORT) 1;
+#else
+ *dec = (EMUSHORT) 1;
+#endif
+ /*************************************************************/
+
+ save_carry = __MFLAG(CF);
+ isub_np( c, a, dec, np ); /* Set Flags */
+ if( save_carry ) __STC; /* set carry flag */
+ else __CLC; /* clear carry flag */
+
+ /* FREE inc **********/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*********************/
+}
+
+
+/***************************************************************
+ Операции копирования данных CPY.
+ Воздействует на флаги: OF, PF, SF, ZF.
+ Флаги CF, AF не изменяются.
+ ***************************************************************/
+
+/***********************************
+ Копирование равнозначных [c <= a]
+ ***********************************/
+
+void icpy_8( __mpu_uint8_t *c, __mpu_uint8_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+
+}
+
+void icpy_16( __mpu_uint16_t *c, __mpu_uint16_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+
+}
+
+void icpy_32( __mpu_uint32_t *c, __mpu_uint32_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = *a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+
+}
+
+static void scpy_s2s_np( EMUSHORT *c, EMUSHORT *a, int np )
+{
+ EMUSHORT *x;
+ signed int zero = 1;
+ signed int i;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = a;
+ i = 0;
+
+ c[i] = *x;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++i;
+
+ while( i < np )
+ {
+ c[i] = *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++i;
+ }
+
+ if( zero ) __STZ; /* set zero flag */
+ else __CLZ; /* clear zero flag */
+
+ --i;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ if( c[i] & MASK_SIGN ) __STS;
+#endif
+}
+
+
+/*****************************************************
+ Копирование меньших в большие [short to long (s2l)]
+ *****************************************************/
+/**************
+ from 8-bit:
+ */
+void icpy_s2l_8to16( __mpu_uint16_t *c, __mpu_uint8_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint16_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icpy_s2l_8to32( __mpu_uint32_t *c, __mpu_uint8_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint32_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icpy_s2l_8to_np( EMUSHORT *c, __mpu_uint8_t *a, int np )
+{
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_s2l_8to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = (EMUSHORT)0;
+ --i;
+ }
+ c[i] = (EMUSHORT)0; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = (EMUSHORT)0;
+ ++i;
+ }
+#endif
+}
+
+/**************
+ from 16-bit:
+ */
+void icpy_s2l_16to32( __mpu_uint32_t *c, __mpu_uint16_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint32_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icpy_s2l_16to_np( EMUSHORT *c, __mpu_uint16_t *a, int np )
+{
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_s2l_16to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = (EMUSHORT)0;
+ --i;
+ }
+ c[i] = (EMUSHORT)0; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = (EMUSHORT)0;
+ ++i;
+ }
+#endif
+}
+
+/**************
+ from 32-bit:
+ */
+#if BITS_PER_EMUSHORT > 32
+void icpy_s2l_32to_np( EMUSHORT *c, __mpu_uint32_t *a, int np )
+{
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_s2l_32to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = (EMUSHORT)0;
+ --i;
+ }
+ c[i] = (EMUSHORT)0; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = (EMUSHORT)0;
+ ++i;
+ }
+#endif
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+/***********************************
+ from emushort; size(a) < size(c):
+ */
+static void scpy_s2l_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ EMUSHORT *x;
+ signed int zero = 1;
+ signed int i;
+
+ if( np_c <= np_a || np_c < 1 || np_c > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"scpy_s2l_np (emushort to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np_a - 1;
+ i = np_c - 1;
+#else
+ x = a;
+ i = 0;
+#endif
+
+ c[i] = *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --i;
+ /* если (np_c == np_a) то цикл бесконечен */
+ while( i >= (np_c - np_a) )
+ {
+ c[i]= *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ --x; --i;
+ }
+#else
+ ++x; ++i;
+ while( i < np_a )
+ {
+ c[i]= *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++i;
+ }
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+ {
+ c[i] = (EMUSHORT)0;
+ --i;
+ }
+ c[i] = (EMUSHORT)0; /* i = 0 */
+#else
+ while( i < np_c )
+ {
+ c[i] = (EMUSHORT)0;
+ ++i;
+ }
+#endif
+
+ if( zero ) __STZ;
+ else __CLZ;
+}
+
+
+/*****************************************************
+ Копирование больших в меньшие [long to short (l2s)]
+ *****************************************************/
+/**************
+ into 8-bit:
+ */
+void icpy_l2s_16to8( __mpu_uint8_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t x;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+
+ x >>= 8;
+ if( x ) __STO;
+
+ *c = (__mpu_uint8_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+}
+
+void icpy_l2s_32to8( __mpu_uint8_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t x;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+
+ x >>= 8;
+ if( x ) __STO;
+
+ *c = (__mpu_uint8_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+}
+
+void icpy_l2s_np_to8( __mpu_uint8_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_l2s_np_to8 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+
+ y >>= 8;
+ if( y ) __STO;
+
+ *c = (__mpu_uint8_t)*x;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( *x ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80 ) __STS;
+}
+
+/**************
+ into 16-bit:
+ */
+void icpy_l2s_32to16( __mpu_uint16_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t x;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+
+ x >>= 16;
+ if( x ) __STO;
+
+ *c = (__mpu_uint16_t)*a;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+}
+
+void icpy_l2s_np_to16( __mpu_uint16_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_l2s_np_to16 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+
+ y >>= 16;
+ if( y ) __STO;
+
+ *c = (__mpu_uint16_t)*x;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( *x ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x8000 ) __STS;
+}
+
+/**************
+ into 32-bit:
+ */
+#if BITS_PER_EMUSHORT > 32
+void icpy_l2s_np_to32( __mpu_uint32_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_l2s_np_to32 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+
+ y >>= 32;
+ if( y ) __STO;
+
+ *c = (__mpu_uint32_t)*x;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( *x ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+ if( *c & 0x80000000 ) __STS;
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+/************************************
+ into emushort; size(a) >= size(c):
+ */
+static void scpy_l2s_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ EMUSHORT *y, *x;
+ signed int zero = 1;
+ signed int i;
+
+ if( np_a < np_c || np_a < 1 || np_a > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"scpy_l2s_np (emushort to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np_a - 1;
+ y = c + np_c - 1;
+#else
+ x = a;
+ y = c;
+#endif
+
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ i = 1;
+ while( i < np_c )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ ++i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( *y & MASK_SIGN ) __STS;
+
+ while( i < np_a )
+ {
+ if( *x ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ ++i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+}
+
+/*****************************************************
+ Копирование ALL LONG WORD [c <== a]
+ *****************************************************/
+void icpy_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ if( np_a < 1 || np_c < 1 || np_a > NP_MAX || np_c > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icpy_np (emushort)" );
+ return;
+ }
+
+ if( np_c > np_a )
+ {
+ scpy_s2l_np( c, a, np_c, np_a );
+ return;
+ }
+
+ if( np_c < np_a )
+ {
+ scpy_l2s_np( c, a, np_c, np_a );
+ return;
+ }
+
+ if( np_c == np_a )
+ {
+ scpy_s2s_np( c, a, np_a );
+ return;
+ }
+}
+
+
+/***************************************************************
+ Операции преобразования (convert) данных CVT.
+ Воздействует на флаги: OF, PF, SF, ZF.
+ Флаги CF, AF не изменяются.
+ ***************************************************************/
+
+/*****************************************
+ Преобразование равнозначных не нужно,
+ можно использовать функции копирования:
+
+ void icpy_8();
+ void icpy_16();
+ #if BITS_PER_EMUSHORT > 32
+ void icpy_32();
+ #endif // BITS_PER_EMUSHORT > 32
+ static void scpy_s2s_np();
+ *****************************************/
+
+/********************************************************
+ Преобразование меньших в большие [short to long (s2l)]
+ ********************************************************/
+/**************
+ from 8-bit:
+ */
+void icvt_s2l_8to16( __mpu_uint16_t *c, __mpu_uint8_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint16_t)*a;
+
+ if( *a & 0x80 ) { *c |= 0xff00; __STS; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_s2l_8to32( __mpu_uint32_t *c, __mpu_uint8_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint32_t)*a;
+
+ if( *a & 0x80 ) { *c |= 0xffffff00; __STS; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_s2l_8to_np( EMUSHORT *c, __mpu_uint8_t *a, int np )
+{
+ EMUSHORT save_sign = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_s2l_8to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( *a & 0x80 )
+ {
+ save_sign = (EMUSHORT)MASK_ALL_BITS;
+ c[i] |= (save_sign << 8);
+ __STS;
+ }
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = save_sign;
+ --i;
+ }
+ c[i] = save_sign; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = save_sign;
+ ++i;
+ }
+#endif
+}
+
+/**************
+ from 16-bit:
+ */
+void icvt_s2l_16to32( __mpu_uint32_t *c, __mpu_uint16_t *a )
+{
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ *c = (__mpu_uint32_t)*a;
+
+ if( *a & 0x8000 ) { *c |= 0xffff0000; __STS; }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_s2l_16to_np( EMUSHORT *c, __mpu_uint16_t *a, int np )
+{
+ EMUSHORT save_sign = 0;
+ signed int i;
+
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_s2l_16to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( *a & 0x8000 )
+ {
+ save_sign = (EMUSHORT)MASK_ALL_BITS;
+ c[i] |= (save_sign << 16);
+ __STS;
+ }
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = save_sign;
+ --i;
+ }
+ c[i] = save_sign; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = save_sign;
+ ++i;
+ }
+#endif
+}
+
+#if BITS_PER_EMUSHORT > 32
+/**************
+ from 32-bit:
+ */
+void icvt_s2l_32to_np( EMUSHORT *c, __mpu_uint32_t *a, int np )
+{
+ EMUSHORT save_sign = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_s2l_32to_np (to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ i = np - 1;
+#else
+ i = 0;
+#endif
+
+ c[i] = (EMUSHORT)*a;
+
+ if( *a & 0x80000000 )
+ {
+ save_sign = (EMUSHORT)MASK_ALL_BITS;
+ c[i] |= (save_sign << 32);
+ __STS;
+ }
+
+ if( c[i] == 0 ) __STZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --i;
+ while( i > 0 )
+ {
+ c[i] = save_sign;
+ --i;
+ }
+ c[i] = save_sign; /* i == 0 */
+#else
+ ++i;
+ while( i < np )
+ {
+ c[i] = save_sign;
+ ++i;
+ }
+#endif
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+/************************************
+ from emushort; size(a) < size(c):
+ */
+static void scvt_s2l_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ EMUSHORT *x, save_sign = 0;
+ signed int zero = 1;
+ signed int i;
+
+ if( np_c <= np_a || np_c < 1 || np_c > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"scvt_s2l_np (emushort to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np_a - 1;
+ i = np_c - 1;
+#else
+ x = a;
+ i = 0;
+#endif
+
+ c[i] = *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --i;
+ /* если (np_c == np_a) то цикл бесконечен */
+ while( i >= (np_c - np_a) )
+ {
+ c[i]= *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ --x; --i;
+ }
+#else
+ ++x; ++i;
+ while( i < np_a )
+ {
+ c[i]= *x;
+
+ if( c[i] ) zero &= 0;
+ else zero &= 1;
+
+ ++x; ++i;
+ }
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x;
+#else
+ --x;
+#endif
+ if( *x & MASK_SIGN )
+ {
+ save_sign = (EMUSHORT)MASK_ALL_BITS;
+ __STS;
+ zero &= 0;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( i > 0 )
+ {
+ c[i] = save_sign;
+ --i;
+ }
+ c[i] = save_sign; /* i == 0 */
+#else
+ while( i < np_c )
+ {
+ c[i] = save_sign;
+ ++i;
+ }
+#endif
+
+ if( zero ) __STZ;
+ else __CLZ;
+}
+
+
+/********************************************************
+ Преобразование больших в меньшие [long to short (l2s)]
+ ********************************************************/
+/**************
+ into 8-bit:
+ */
+void icvt_l2s_16to8( __mpu_uint8_t *c, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t x;
+ signed int sign = 0, save_sign = 0;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+ if( x & 0x8000 ) save_sign = 1;
+ if( x & 0x80 ) sign = 1;
+
+ x &= 0xff00;
+ if( !(( save_sign && sign && (x == 0xff00)) ||
+ (!save_sign && !sign && (x == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint8_t)*a;
+
+ if( save_sign ) *c |= 0x80;
+ else *c &= 0x7f;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_l2s_32to8( __mpu_uint8_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t x;
+ signed int sign = 0, save_sign = 0;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+ if( x & 0x80000000 ) save_sign = 1;
+ if( x & 0x80 ) sign = 1;
+
+ x &= 0xffffff00;
+ if( !(( save_sign && sign && (x == 0xffffff00)) ||
+ (!save_sign && !sign && (x == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint8_t)*a;
+
+ if( save_sign ) *c |= 0x80;
+ else *c &= 0x7f;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_l2s_np_to8( __mpu_uint8_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int sign = 0, save_sign = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_l2s_np_to8 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np - 1;
+#endif
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+ if( y & 0x80 ) sign = 1;
+
+ y &= ((EMUSHORT)MASK_ALL_BITS) << 8;
+ if( !(( save_sign && sign &&
+ (y == (((EMUSHORT)MASK_ALL_BITS) << 8))) ||
+ (!save_sign && !sign && (y == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint8_t)*x;
+
+ if( save_sign ) *c |= 0x80;
+ else *c &= 0x7f;
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( !(( save_sign && sign &&
+ (*x == ((EMUSHORT)MASK_ALL_BITS))) ||
+ (!save_sign && !sign && (*x == 0))
+ )
+ ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+/**************
+ into 16-bit:
+ */
+void icvt_l2s_32to16( __mpu_uint16_t *c, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t x;
+ signed int sign = 0, save_sign = 0;
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+ x = *a;
+ if( x & 0x80000000 ) save_sign = 1;
+ if( x & 0x8000 ) sign = 1;
+
+ x &= 0xffff0000;
+ if( !(( save_sign && sign && (x == 0xffff0000)) ||
+ (!save_sign && !sign && (x == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint16_t)*a;
+
+ if( save_sign ) *c |= 0x8000;
+ else *c &= 0x7fff;
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+ if( *c == 0 ) __STZ;
+}
+
+void icvt_l2s_np_to16( __mpu_uint16_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int sign = 0, save_sign = 0;
+ signed int i;
+
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_l2s_np_to16 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np - 1;
+#endif
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+ if( y & 0x8000 ) sign = 1;
+
+ y &= ((EMUSHORT)MASK_ALL_BITS) << 16;
+ if( !(( save_sign && sign &&
+ (y == (((EMUSHORT)MASK_ALL_BITS) << 16))) ||
+ (!save_sign && !sign && (y == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint16_t)*x;
+
+ if( save_sign ) *c |= 0x8000;
+ else *c &= 0x7fff;
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( !(( save_sign && sign &&
+ (*x == ((EMUSHORT)MASK_ALL_BITS))) ||
+ (!save_sign && !sign && (*x == 0))
+ )
+ ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+
+/**************
+ into 32-bit:
+ */
+#if BITS_PER_EMUSHORT > 32
+void icvt_l2s_np_to32( __mpu_uint32_t *c, EMUSHORT *a, int np )
+{
+ EMUSHORT y, *x;
+ signed int sign = 0, save_sign = 0;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_l2s_np_to32 (from emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np - 1;
+#endif
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np - 1;
+#else
+ x = a;
+#endif
+ y = *x;
+ if( y & 0x80000000 ) sign = 1;
+
+ y &= ((EMUSHORT)MASK_ALL_BITS) << 32;
+ if( !(( save_sign && sign &&
+ (y == (((EMUSHORT)MASK_ALL_BITS) << 32))) ||
+ (!save_sign && !sign && (y == 0))
+ )
+ ) __STO;
+
+ *c = (__mpu_uint32_t)*x;
+
+ if( save_sign ) *c |= 0x80000000;
+ else *c &= 0x7fffffff;
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ i = np - 1;
+ while( i > 0 )
+ {
+ if( !(( save_sign && sign &&
+ (*x == ((EMUSHORT)MASK_ALL_BITS))) ||
+ (!save_sign && !sign && (*x == 0))
+ )
+ ) __STO;
+
+#if MPU_WORD_ORDER_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ --i;
+ }
+
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+
+ if( *c == 0 ) __STZ;
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+/************************************
+ into emushort; size(a) >= size(c):
+ */
+static void scvt_l2s_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ EMUSHORT *y, *x;
+ signed int sign = 0, save_sign = 0, zero = 1;
+ signed int i;
+
+ if( np_a < np_c || np_a < 1 || np_a > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"scvt_l2s_np (emushort to emushort)" );
+ return;
+ }
+
+ /* AF (aux carry) = 0; Не определяем. */
+ /* CF (carry) = 0; Не определяем. */
+ __CLEAR_IFLAGS;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a;
+#else
+ x = a + np_a - 1;
+#endif
+ if( *x & MASK_SIGN ) save_sign = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = a + np_a - 1;
+ y = c + np_c - 1;
+#else
+ x = a;
+ y = c;
+#endif
+
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 0
+ ++x; ++y;
+#endif
+ i = 1;
+ while( i < np_c )
+ {
+ *y = *x;
+
+ if( *y ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x; --y;
+#else
+ ++x; ++y;
+#endif
+ ++i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++x;
+#else
+ --x;
+#endif
+ if( *x & MASK_SIGN ) sign = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++y;
+#else
+ --y;
+#endif
+ if( save_sign )
+ {
+ *y |= ((EMUSHORT)MASK_ALL_BITS) <<
+ (BITS_PER_EMUSHORT-1);
+ zero &= 0;
+ }
+ else
+ {
+ *y &= ((EMUSHORT)MASK_ALL_BITS) >> 1;
+ zero &= 1;
+ }
+
+ if( save_sign ) __STS;
+ else __CLS;
+
+ while( i < np_a )
+ {
+ if( !(( save_sign && sign &&
+ (*x == ((EMUSHORT)MASK_ALL_BITS))) ||
+ (!save_sign && !sign && (*x == 0))
+ )
+ ) __STO;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --x;
+#else
+ ++x;
+#endif
+ ++i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+}
+
+/*****************************************************
+ Преобразование ALL LONG WORD [c <== a].
+ *****************************************************/
+void icvt_np( EMUSHORT *c, EMUSHORT *a, int np_c, int np_a )
+{
+ if( np_a < 1 || np_c < 1 || np_a > NP_MAX || np_c > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"icvt_np (emushort)" );
+ return;
+ }
+
+ if( np_c > np_a )
+ {
+ scvt_s2l_np( c, a, np_c, np_a );
+ return;
+ }
+
+ if( np_c < np_a )
+ {
+ scvt_l2s_np( c, a, np_c, np_a );
+ return;
+ }
+
+ if( np_c == np_a )
+ {
+ scpy_s2s_np( c, a, np_a );
+ return;
+ }
+}
+
+
+/***************************************************************
+ Операция XCHG (замена) [a <==> b].
+ Не изменяет флаги.
+ ***************************************************************/
+
+void ixchg_8( __mpu_uint8_t *a, __mpu_uint8_t *b )
+{
+ __mpu_uint8_t xchg;
+
+ xchg = *a;
+ *a = *b;
+ *b = xchg;
+}
+
+void ixchg_16( __mpu_uint16_t *a, __mpu_uint16_t *b )
+{
+ __mpu_uint16_t xchg;
+
+ xchg = *a;
+ *a = *b;
+ *b = xchg;
+}
+
+void ixchg_32( __mpu_uint32_t *a, __mpu_uint32_t *b )
+{
+ __mpu_uint32_t xchg;
+
+ xchg = *a;
+ *a = *b;
+ *b = xchg;
+}
+
+void ixchg_np( EMUSHORT *a, EMUSHORT *b, int np )
+{
+ EMUSHORT xchg, *y, *x;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ixchg_np (emushort)" );
+ return;
+ }
+
+ x = a;
+ y = b;
+ i = np;
+
+ while( i > 0 )
+ {
+ xchg = *x;
+ *x = *y;
+ *y = xchg;
+
+ ++x; ++y;
+ --i;
+ }
+}
+
+
+/***************************************************************
+ Операции беззнакового и знакового умножения.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+/***************************************************************
+ Операция беззнакового умножения MUL.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+/*********************
+ prod - произведение
+ num - множимое
+ mul - множитель
+ *********************/
+void imul_8( __mpu_uint16_t *prod, __mpu_uint8_t *num, __mpu_uint8_t *mul )
+{
+ __mpu_uint16_t pcpy = 0;
+ signed int i, k, shifts = 0;
+
+ icpy_s2l_8to16( &pcpy, num );
+
+ *prod = 0;
+
+ k = BITS_PER_BYTE;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (*mul >> ((i)&(BITS_PER_BYTE-1)))&1 /*BIT(&mul,i)*/ )
+ {
+ ishln_16( &pcpy, &pcpy, shifts );
+ iadd_16( prod, prod, &pcpy ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_16 */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 8 ) __STR;
+ else __CLR;
+}
+
+void imul_16( __mpu_uint32_t *prod, __mpu_uint16_t *num, __mpu_uint16_t *mul )
+{
+ __mpu_uint32_t pcpy = 0;
+ signed int i, k, shifts = 0;
+
+ icpy_s2l_16to32( &pcpy, num );
+
+ *prod = 0;
+
+ k = BITS_PER_TWO_BYTES;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (*mul >> ((i)&(BITS_PER_TWO_BYTES-1)))&1 /*BIT(&mul,i)*/ )
+ {
+ ishln_32( &pcpy, &pcpy, shifts );
+ iadd_32( prod, prod, &pcpy ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_32 */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 16 ) __STR;
+ else __CLR;
+}
+
+#if BITS_PER_EMUSHORT > 32 /* 64 bits only */
+void imul_32( __mpu_uint64_t *prod, __mpu_uint32_t *num, __mpu_uint32_t *mul )
+{
+ __mpu_uint64_t pcpy = 0;
+ signed int i, k, shifts = 0;
+
+ icpy_s2l_32to_np( (EMUSHORT *)(&pcpy), num, 1 );
+ /*
+ NOTE:
+ Размер EMUSHORT в зависимости от машины может принимать
+ значения 32, 64, 128, ...
+ Если BITS_PER_EMUSHORT > 32,
+ То между директивами препроцессора
+ #if BITS_PER_EMUSHORT > 32
+ #endif // BITS_PER_EMUSHORT > 32
+ мы рассматриваем случай когда BITS_PER_EMUSHORT == 64,
+ а размер __mpu_uint64_t всегда 64 бита.
+
+ Следовательно здесь размеры BITS_PER_EMUSHORT и
+ __mpu_uint64_t равны;
+ */
+
+ *prod = 0;
+
+ k = BITS_PER_FOUR_BYTES;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (*mul >> ((i)&(BITS_PER_FOUR_BYTES-1)))&1 /*BIT(&mul,i)*/ )
+ {
+ ishln_np( (EMUSHORT *)(&pcpy),
+ (EMUSHORT *)(&pcpy), shifts,
+ 1 );
+ iadd_np( (EMUSHORT *)prod,
+ (EMUSHORT *)prod,
+ (EMUSHORT *)(&pcpy),
+ 1 ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np (emushort) */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 32 ) __STR;
+ else __CLR;
+
+ /***************************************************
+ Проверить работу функции на 32 разрядной машине
+ можно если вместо размера 1 в функциях:
+ icpy_s2l_32to_np,
+ ishln_np,
+ iadd_np
+ поставить
+ 64 / BITS_PER_EMUSHORT,
+ и убрать директивы условной компиляции, в которые
+ заключена данная функция.
+ ***************************************************/
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+/***************************************************************
+ Операция знакового умножения SMUL.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+void ismul_8( __mpu_uint16_t *prod, __mpu_uint8_t *num, __mpu_uint8_t *mul )
+{
+ __mpu_uint16_t pcpy_num = 0, pcpy_mul = 0;
+ signed int sign_num = 0, sign_mul = 0;
+ signed int i, k, shifts = 0;
+
+ if( *num & 0x80 ) sign_num = 1;
+ if( *mul & 0x80 ) sign_mul = 1;
+
+ icvt_s2l_8to16( &pcpy_num, num );
+ icvt_s2l_8to16( &pcpy_mul, mul );
+
+ *prod = 0;
+
+ if( sign_num ) ineg_16( &pcpy_num, &pcpy_num );
+ if( sign_mul ) ineg_16( &pcpy_mul, &pcpy_mul );
+
+ k = BITS_PER_BYTE;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (pcpy_mul >> ((i)&(BITS_PER_BYTE-1)))&1 /*BIT(&mul,i)*/ )
+ {
+ ishln_16( &pcpy_num, &pcpy_num, shifts );
+ iadd_16( prod, prod, &pcpy_num ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 7 ) __STR;
+ else __CLR;
+
+ if( sign_num ^ sign_mul ) ineg_16( prod, prod );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_16 or ineg_16 */
+
+ /* if( OF ) RF (major/remainder) is Not Correct */
+}
+
+void ismul_16( __mpu_uint32_t *prod, __mpu_uint16_t *num, __mpu_uint16_t *mul )
+{
+ __mpu_uint32_t pcpy_num = 0, pcpy_mul = 0;
+ signed int sign_num = 0, sign_mul = 0;
+ signed int i, k, shifts = 0;
+
+ if( *num & 0x8000 ) sign_num = 1;
+ if( *mul & 0x8000 ) sign_mul = 1;
+
+ icvt_s2l_16to32( &pcpy_num, num );
+ icvt_s2l_16to32( &pcpy_mul, mul );
+
+ *prod = 0;
+
+ if( sign_num ) ineg_32( &pcpy_num, &pcpy_num );
+ if( sign_mul ) ineg_32( &pcpy_mul, &pcpy_mul );
+
+ k = BITS_PER_TWO_BYTES;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (pcpy_mul >> ((i)&(BITS_PER_TWO_BYTES-1)))&1 )
+ { /*BIT(&mul,i)*/
+ ishln_32( &pcpy_num, &pcpy_num, shifts );
+ iadd_32( prod, prod, &pcpy_num ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 15 ) __STR;
+ else __CLR;
+
+ if( sign_num ^ sign_mul ) ineg_32( prod, prod );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_32 or ineg_32 */
+
+ /* if( OF ) RF (major/remainder) is Not Correct */
+}
+
+#if BITS_PER_EMUSHORT > 32
+void ismul_32( __mpu_uint64_t *prod, __mpu_uint32_t *num, __mpu_uint32_t *mul )
+{
+ __mpu_uint64_t pcpy_num = 0, pcpy_mul = 0;
+ signed int sign_num = 0, sign_mul = 0;
+ signed int i, k, shifts = 0;
+
+ if( *num & 0x80000000 ) sign_num = 1;
+ if( *mul & 0x80000000 ) sign_mul = 1;
+
+ icvt_s2l_32to_np( (EMUSHORT *)(&pcpy_num), num, 1 );
+ icvt_s2l_32to_np( (EMUSHORT *)(&pcpy_mul), mul, 1 );
+ /*
+ NOTE:
+ Размер EMUSHORT в зависимости от машины может принимать
+ значения 32, 64, 128, ...
+ Если BITS_PER_EMUSHORT > 32,
+ То между директивами препроцессора
+ #if BITS_PER_EMUSHORT > 32
+ #endif // BITS_PER_EMUSHORT > 32
+ мы рассматриваем случай когда BITS_PER_EMUSHORT == 64,
+ а размер __mpu_uint64_t всегда 64 бита.
+
+ Следовательно здесь размеры BITS_PER_EMUSHORT и
+ __mpu_uint64_t равны;
+ */
+
+ *prod = (__mpu_uint64_t)0;
+
+ if( sign_num ) ineg_np( (EMUSHORT *)(&pcpy_num),
+ (EMUSHORT *)(&pcpy_num), 1 );
+ if( sign_mul ) ineg_np( (EMUSHORT *)(&pcpy_mul),
+ (EMUSHORT *)(&pcpy_mul), 1 );
+
+ k = BITS_PER_FOUR_BYTES;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( (pcpy_mul >> ((i)&(BITS_PER_FOUR_BYTES-1)))&1 /*BIT(&mul,i)*/ )
+ {
+ ishln_np( (EMUSHORT *)(&pcpy_num),
+ (EMUSHORT *)(&pcpy_num),
+ shifts, 1 );
+ iadd_np( (EMUSHORT *)prod,
+ (EMUSHORT *)prod,
+ (EMUSHORT *)(&pcpy_num),
+ 1 ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ /* set RF (major/remainder) flag */
+ if( *prod >> 31 ) __STR;
+ else __CLR;
+
+ if( sign_num ^ sign_mul )
+ ineg_np( (EMUSHORT *)prod, (EMUSHORT *)prod, 1 );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np (emushort) or ineg_np (prod) */
+
+ /* if( OF ) RF (major/remainder) is Not Correct */
+
+ /***************************************************
+ Проверить работу функции на 32 разрядной машине
+ можно если вместо размера 1 в функциях:
+ icvt_s2l_32to_np,
+ ishln_np,
+ iadd_np,
+ ineg_np
+ поставить
+ 64 / BITS_PER_EMUSHORT,
+ и убрать директивы условной компиляции, в которые
+ заключена данная функция.
+ ***************************************************/
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+/***************************************************************
+ Операции беззнакового и знакового деления.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+/***************************************************************
+ Операция беззнакового деления DIV.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+/*****************
+ quot - частное
+ rem - остаток
+ num - делимое
+ den - делитель
+ *****************/
+void idiv_8( __mpu_uint8_t *quot, __mpu_uint8_t *rem, __mpu_uint8_t *num, __mpu_uint8_t *den )
+{
+ __mpu_uint8_t cpy_num = 0, cpy_den = 0, j;
+ signed int i, k;
+ int b, bnum, bden;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ b = BITS_PER_BYTE - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_BYTE-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_BYTE - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_BYTE-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ *quot = 0xff;
+
+ __STC; __STO; __STS; __STP; /* __MPARITY(ff) == 1 */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_8( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_8( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_8( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_8( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_8( &cpy_den, &cpy_den );
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x80 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+}
+
+void idiv_16( __mpu_uint16_t *quot, __mpu_uint16_t *rem, __mpu_uint16_t *num, __mpu_uint16_t *den )
+{
+ __mpu_uint16_t cpy_num = 0, cpy_den = 0, j;
+ signed int i, k;
+ int b, bnum, bden;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ b = BITS_PER_TWO_BYTES - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_TWO_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_TWO_BYTES - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_TWO_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ *quot = 0xffff;
+
+ __STC; __STO; __STS; __STP; /* __MPARITY(ff) == 1 */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_16( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_16( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_16( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_16( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_16( &cpy_den, &cpy_den );
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x8000 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+}
+
+#if BITS_PER_EMUSHORT > 32
+void idiv_32( __mpu_uint32_t *quot, __mpu_uint32_t *rem, __mpu_uint32_t *num, __mpu_uint32_t *den )
+{
+ __mpu_uint32_t cpy_num = 0, cpy_den = 0, j;
+ signed int i, k;
+ int b, bnum, bden;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ b = BITS_PER_FOUR_BYTES - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_FOUR_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_FOUR_BYTES - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_FOUR_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ *quot = 0xffffffff;
+
+ __STC; __STO; __STS; __STP; /* __MPARITY(ff) == 1 */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_32( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_32( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_32( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_32( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_32( &cpy_den, &cpy_den );
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x80000000 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+/***************************************************************
+ Операция знакового деления SDIV.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+void isdiv_8( __mpu_uint8_t *quot, __mpu_uint8_t *rem, __mpu_uint8_t *num, __mpu_uint8_t *den )
+{
+ __mpu_uint8_t cpy_num = 0, cpy_den = 0, j = 0;
+ signed int sign_num = 0, sign_den = 0;
+ signed int i, k;
+ int b, bnum, bden;
+
+ if( *num & 0x80 ) sign_num = 1;
+ if( *den & 0x80 ) sign_den = 1;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ if( sign_num ) ineg_8( &cpy_num, &cpy_num );
+ if( sign_den ) ineg_8( &cpy_den, &cpy_den );
+
+
+ b = BITS_PER_BYTE - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_BYTE-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_BYTE - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_BYTE-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ if( sign_num ) ineg_8( &cpy_num, &cpy_num );
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( !sign_num ) j = 0xff;
+ *quot = j;
+
+ if( !sign_num )
+ {
+ *quot ^= 0x80;
+ __CLS; /* Sign Flag */
+ }
+ else
+ {
+ *quot |= 0x80;
+ __STS; /* Sign Flag */
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __STC; /* Carry Flag */
+ __STO; /* Overflow Flag */
+ __CLZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den ) ineg_8( rem, rem );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+ __CLS; /* Sign Flag */
+ __STZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_8( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_8( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_8( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_8( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_8( &cpy_den, &cpy_den );
+ }
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den )
+ {
+ ineg_8( rem, rem );
+ ineg_8( quot, quot );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+
+ if( __MFLAG(SF) == (sign_num ^ sign_den) )
+ /* if( Correct result Sign ) */
+ __CLO; /* Overflow Flag */
+
+ /* flags:
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last ineg_8() */
+
+ return;
+ }
+
+ /* z = quot */
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x80 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+ /* т.к. здесь идет речь о положительных числах
+ (именно в их знаковом представлении 011111)
+ наличие 1 в старшем разряде недопустимо */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+}
+
+void isdiv_16( __mpu_uint16_t *quot, __mpu_uint16_t *rem, __mpu_uint16_t *num, __mpu_uint16_t *den )
+{
+ __mpu_uint16_t cpy_num = 0, cpy_den = 0, j = 0;
+ signed int sign_num = 0, sign_den = 0;
+ signed int i, k;
+ int b, bnum, bden;
+
+ if( *num & 0x8000 ) sign_num = 1;
+ if( *den & 0x8000 ) sign_den = 1;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ if( sign_num ) ineg_16( &cpy_num, &cpy_num );
+ if( sign_den ) ineg_16( &cpy_den, &cpy_den );
+
+ b = BITS_PER_TWO_BYTES - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_TWO_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_TWO_BYTES - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_TWO_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ if( sign_num ) ineg_16( &cpy_num, &cpy_num );
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( !sign_num ) j = 0xffff;
+ *quot = j;
+
+ if( !sign_num )
+ {
+ *quot ^= 0x8000;
+ __CLS; /* Sign Flag */
+ }
+ else
+ {
+ *quot |= 0x8000;
+ __STS; /* Sign Flag */
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __STC; /* Carry Flag */
+ __STO; /* Overflow Flag */
+ __CLZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den ) ineg_16( rem, rem );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+ __CLS; /* Sign Flag */
+ __STZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_16( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_16( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_16( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_16( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_16( &cpy_den, &cpy_den );
+ }
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den )
+ {
+ ineg_16( rem, rem );
+ ineg_16( quot, quot );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+
+ if( __MFLAG(SF) == (sign_num ^ sign_den) )
+ /* if( Correct result Sign ) */
+ __CLO; /* Overflow Flag */
+
+ /* flags:
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last ineg_16() */
+
+ return;
+ }
+
+ /* z = quot */
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x8000 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+ /* т.к. здесь идет речь о положительных числах
+ (именно в их знаковом представлении 011111)
+ наличие 1 в старшем разряде недопустимо */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+}
+
+#if BITS_PER_EMUSHORT > 32
+void isdiv_32( __mpu_uint32_t *quot, __mpu_uint32_t *rem, __mpu_uint32_t *num, __mpu_uint32_t *den )
+{
+ __mpu_uint32_t cpy_num = 0, cpy_den = 0, j = 0;
+ signed int sign_num = 0, sign_den = 0;
+ signed int i, k;
+ int b, bnum, bden;
+
+ if( *num & 0x80000000 ) sign_num = 1;
+ if( *den & 0x80000000 ) sign_den = 1;
+
+ cpy_num = *num;
+ cpy_den = *den;
+
+ *quot = 0;
+ *rem = 0;
+
+ if( sign_num ) ineg_32( &cpy_num, &cpy_num );
+ if( sign_den ) ineg_32( &cpy_den, &cpy_den );
+
+ b = BITS_PER_FOUR_BYTES - 1;
+ while( !((cpy_num >> ((b)&(BITS_PER_FOUR_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_num,b) */
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ b = BITS_PER_FOUR_BYTES - 1;
+ while( !((cpy_den >> ((b)&(BITS_PER_FOUR_BYTES-1)))&1) &&
+ b != (-1) ) --b; /* !BIT(cpy_den,b) */
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ if( sign_num ) ineg_32( &cpy_num, &cpy_num );
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( !sign_num ) j = 0xffffffff;
+ *quot = j;
+
+ if( !sign_num )
+ {
+ *quot ^= 0x80000000;
+ __CLS; /* Sign Flag */
+ }
+ else
+ {
+ *quot |= 0x80000000;
+ __STS; /* Sign Flag */
+ }
+
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __STC; /* Carry Flag */
+ __STO; /* Overflow Flag */
+ __CLZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den ) ineg_32( rem, rem );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+ __CLS; /* Sign Flag */
+ __STZ; /* Zero Flag */
+ __CLV; /* Invalid Flag */
+
+ __CLP; /* __MPARITY(0) == 0 */
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_32( &cpy_den, &cpy_den, k ); /* value(k) my be zero */
+
+ ++k;
+
+ for( i = 0; i < k; ++i )
+ {
+ icmp_32( &cpy_num, &cpy_den );
+ if( !__MFLAG(SF) )
+ {
+ isub_32( &cpy_num, &cpy_num, &cpy_den );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_32( quot, quot ); /* shift to 1 */
+ *quot |= j;
+
+ ishr_32( &cpy_den, &cpy_den );
+ }
+
+
+ /* copy cpy_num to rem */
+ *rem = cpy_num;
+ if( *rem ) __STR;
+ else __CLR; /* RF=1, if(rem != 0) */
+
+ if( sign_num ^ sign_den )
+ {
+ ineg_32( rem, rem );
+ ineg_32( quot, quot );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* Carry Flag */
+
+ if( __MFLAG(SF) == (sign_num ^ sign_den) )
+ /* if( Correct result Sign ) */
+ __CLO; /* Overflow Flag */
+
+ /* flags:
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last ineg_32() */
+
+ return;
+ }
+
+ /* z = quot */
+ if( __MPARITY(*quot) ) __STP; /* set parity flag */
+ else __CLP; /* clear parity flag */
+
+ if( *quot ) __CLZ;
+ else __STZ;
+
+ if( *quot & 0x80000000 ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+ /* т.к. здесь идет речь о положительных числах
+ (именно в их знаковом представлении 011111)
+ наличие 1 в старшем разряде недопустимо */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* carry flag */
+
+ __CLV; /* clear invalid flag */
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+#if 1 /* Use CPU mul/div */
+/***************************************************************
+ С использованием операций умножения процессора (CPU):
+ ***************************************************************/
+
+/***************************************************************
+ Radix MAX[EMUSHORT] versions of multiply and divide.
+ if BITS_PER_EMUSHORT == 16(от 0 до 65 535),
+ then Radix = 65 536;
+ if BITS_PER_EMUSHORT == 32(от 0 до 4 294 967 295),
+ then Radix = 4 294 967 296;
+ if BITS_PER_EMUSHORT == 64(от 0 до 18 446 744 073 709 551 616),
+ then Radix = 18 446 744 073 709 551 616;
+ etc.
+ ***************************************************************/
+/***************************************************************
+ prod - произведение
+ num - множимое
+ mul - множитель
+ np_prod - размер произведения
+ np_num - размер множимого
+ */
+static void iEMUSHORTm( EMUSHORT *prod, EMUSHORT *num, EMUSHORT mul, int np_prod, int np_num )
+/*******************************************************
+ Multiply integer number NUM
+ by BITS_PER_EMUSHORT-bit quantity MUL,
+ return integer result to PROD.
+ *******************************************************/
+{
+ EMUSHORT *pp, *z;
+ EMULONG carry;
+ EMUSHORT *prd = EMUSHORT_C(0);
+ EMUSHORT *ps;
+ EMULONG a, m;
+ EMUSHORT i;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < np_num + 1 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iEMUSHORTm" );
+ return;
+ }
+
+ /*** Allocate memory for prd . ******************************/
+ prd = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !prd )
+ {
+ /* fatal error */
+ return;
+ }
+ /************************************************************/
+
+ a = mul;
+
+ /* обнуляем произведение */
+ z = prd + np_prod - 1;
+ i = np_prod;
+ while( i > 0 )
+ {
+ *z = (EMUSHORT)0; /* bzero prd */
+ --z; --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ /* младшее слово произведения */
+ pp = &prd[np_prod - 1];
+ /* младшее слово множимого */
+ ps = &num[np_num - 1];
+#else
+ /* младшее слово произведения */
+ pp = &prd[0];
+ /* младшее слово множимого */
+ ps = &num[0];
+#endif
+
+ for( i = 0; i < np_num; ++i )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ m = (EMULONG) a * *ps--;
+#else
+ m = (EMULONG) a * *ps++;
+#endif
+ carry = (m & MASK_ALL_BITS) + *pp;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *pp-- = (EMUSHORT)carry;
+#else
+ *pp++ = (EMUSHORT)carry;
+#endif
+ carry = (carry >> BITS_PER_EMUSHORT) +
+ (m >> BITS_PER_EMUSHORT) + *pp;
+ *pp = (EMUSHORT)carry;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(pp-1) = (EMUSHORT)(carry >> BITS_PER_EMUSHORT);
+#else
+ *(pp+1) = (EMUSHORT)(carry >> BITS_PER_EMUSHORT);
+#endif
+ } /* End for( i = 0; i < np - 1; ++i ) */
+
+ for( i = 0; i < np_prod; ++i ) prod[i] = prd[i];
+
+ /* FREE prd ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /**************************/
+} /* End of iEMUSHORTm() */
+
+/***************************************************************
+ Операции беззнакового и знакового умножения.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+/* Prod = Num * Mul; np_prod == 2*np_num; */
+/****************************
+ prod - произведение
+ num - множимое
+ mul - множитель
+ np_prod - размер произв.
+ np_num - размер множ.
+ ****************************/
+void imul_np( EMUSHORT *prod, EMUSHORT *num, EMUSHORT *mul, int np_prod, int np_num )
+{
+ EMUSHORT *z, *p, *pcpy = 0, *quot = 0;
+ signed int major = 0;
+ signed int i, shifts = 0;
+
+ errno = 0;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < 2*np_num )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"imul_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory for quot **********************************/
+ quot = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !quot )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)quot, 0, np_prod*SIZE_OF_EMUSHORT );
+ /*************************************************************/
+
+ /* Allocate memory for Copy num ******************************/
+ pcpy = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy )
+ {
+ /* fatal error */
+ /* FREE quot *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+ return;
+ }
+ scpy_s2l_np( pcpy, num, np_prod, np_num );
+ /*************************************************************/
+
+ z = prod + np_prod - 1;
+ i = np_prod;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero prod */
+ --z; --i;
+ }
+ /* ++z; */ /* z = prod; */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = mul + np_num - 1;
+#else
+ p = mul; /* z = low part of mul; */
+#endif
+
+ for( i = 0; i < np_num; ++i )
+ {
+ if( *p == (EMUSHORT)0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --p;
+#else
+ ++p;
+#endif
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iEMUSHORTm( prod, pcpy+np_num, *p--, np_prod, np_num );
+#else
+ iEMUSHORTm( prod, pcpy, *p++, np_prod, np_num );
+#endif
+ ishln_np( prod, prod, shifts*BITS_PER_EMUSHORT, np_prod );
+ iadd_np( quot, quot, prod, np_prod ); /* set flags */
+ }
+ ++shifts;
+
+ } /* End for() */
+
+ /* FREE pcpy *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+
+ for( i = 0; i < np_prod; ++i ) prod[i] = quot[i];
+
+ /* FREE quot *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np */
+
+ /* Set RF (major/remainder) flag */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = prod + np_num - 1;
+#else
+ z = prod + np_num;
+#endif
+
+ i = np_num;
+ while( i > 0 )
+ {
+ if( *z ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( major ) __STR;
+ else __CLR;
+}
+
+/* (signed) Prod = Num * Mul; np_prod == 2*np_num; */
+void ismul_np( EMUSHORT *prod, EMUSHORT *num, EMUSHORT *mul, int np_prod, int np_num )
+{
+ EMUSHORT *z, *p;
+ EMUSHORT *pcpy_num = 0, *pcpy_mul = 0, *quot = 0;
+ signed int sign_num = 0, sign_mul = 0, major = 0;
+ signed int i, shifts = 0;
+
+ errno = 0;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < 2*np_num )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ismul_np (emushort)" );
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = num;
+#else
+ p = num + np_num - 1;
+#endif
+ if( *p & MASK_SIGN ) sign_num = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = mul;
+#else
+ p = mul + np_num - 1;
+#endif
+ if( *p & MASK_SIGN ) sign_mul = 1;
+
+ /* Allocate memory for quot **********************************/
+ quot = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !quot )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)quot, 0, np_prod*SIZE_OF_EMUSHORT );
+ /*************************************************************/
+
+ /* Allocate memory for ConVerT num ***************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ /* FREE quot *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+ return;
+ }
+ scvt_s2l_np( pcpy_num, num, np_prod, np_num );
+ /*************************************************************/
+
+ /* Allocate memory for ConVerT mul ***************************/
+ pcpy_mul = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy_mul )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE quot *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+ return;
+ }
+ scvt_s2l_np( pcpy_mul, mul, np_prod, np_num );
+ /*************************************************************/
+
+ z = prod + np_prod - 1;
+ i = np_prod;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Prod */
+ --z; --i;
+ }
+ /* ++z; */ /* z = prod; */
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np_prod );
+ if( sign_mul ) ineg_np( pcpy_mul, pcpy_mul, np_prod );
+
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = pcpy_mul + np_num - 1;
+#else
+ p = pcpy_mul; /* z = low part of mul; */
+#endif
+
+ for( i = 0; i < np_num; ++i )
+ {
+ if( *p == (EMUSHORT)0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --p;
+#else
+ ++p;
+#endif
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iEMUSHORTm( prod, pcpy_num, *p--, np_prod, np_num );
+#else
+ iEMUSHORTm( prod, pcpy_num, *p++, np_prod, np_num );
+#endif
+ ishln_np( prod, prod, shifts*BITS_PER_EMUSHORT, np_prod );
+ iadd_np( quot, quot, prod, np_prod ); /* set flags */
+ }
+ ++shifts;
+
+ } /* End of for( i = 0; i < np_num; ++i ) */
+
+ /* FREE pcpy_mul ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ for( i = 0; i < np_prod; ++i ) prod[i] = quot[i];
+
+ /* FREE quot *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+
+ /* Set RF (major/remainder) flag (with minor sign) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = prod + np_num;
+#else
+ z = prod + np_num - 1;
+#endif
+
+ if( *z & MASK_SIGN ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+
+ i = np_num;
+ while( i > 0 )
+ {
+ if( *z ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( major ) __STR;
+ else __CLR;
+
+ if( sign_num ^ sign_mul ) ineg_np( prod, prod, np_prod );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np or ineg_np */
+
+ /* if( OF ) RF (major/remainder) is Not Correct */
+}
+
+#else /* Do not use CPU mul/div */
+/***************************************************************
+ Без использования операций умножения процессора (CPU):
+ ***************************************************************/
+
+/***************************************************************
+ Операции беззнакового и знакового умножения.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+/* Prod = Num * Mul; np_prod == 2*np_num; */
+void imul_np( EMUSHORT *prod, EMUSHORT *num, EMUSHORT *mul, int np_prod, int np_num )
+{
+ EMUSHORT *z, *x, *y, *pcpy = 0;
+ signed int major = 0;
+ signed int i, k, shifts = 0;
+
+ errno = 0;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < 2*np_num )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"imul_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory for Copy num ******************************/
+ pcpy = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy )
+ {
+ /* fatal error */
+ return;
+ }
+ /* (void)memset( (void *)pcpy, 0, np_prod*SIZE_OF_EMUSHORT ); */
+ scpy_s2l_np( pcpy, num, np_prod, np_num );
+ /*************************************************************/
+
+ z = prod + np_prod - 1;
+ i = np_prod;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Prod */
+ --z; --i;
+ }
+ ++z; /* z = prod; */
+
+ x = pcpy;
+ y = mul;
+
+ k = BITS_PER_EMUSHORT*np_num;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( ORDER_BIT(y,i,np_num) ) /* см. mpu-emutype.h */
+ {
+ /*
+ следующие операции корректно работают
+ при любом MPU_WORD_ORDER_BIG_ENDIAN
+ */
+ ishln_np( x, x, shifts, np_prod );
+ iadd_np( z, z, x, np_prod ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End of for( i = 0; i < k; ++i ) */
+
+ /* FREE pcpy *******************/
+ __mpu_sbrk( -((int)(np_prod*SIZE_OF_EMUSHORT)) );
+ /*******************************/
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np */
+
+ /* Set RF (major/remainder) flag */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = prod + np_num - 1;
+#else
+ z = prod + np_num;
+#endif
+
+ i = np_num;
+ while( i > 0 )
+ {
+ if( *z ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( major ) __STR;
+ else __CLR;
+}
+
+/* (signed) Prod = Num * Mul; np_prod == 2*np_num; */
+void ismul_np( EMUSHORT *prod, EMUSHORT *num, EMUSHORT *mul, int np_prod, int np_num )
+{
+ EMUSHORT *z, *x, *y;
+ EMUSHORT *pcpy_num = 0, *pcpy_mul = 0;
+ signed int sign_num = 0, sign_mul = 0, major = 0;
+ signed int i, k, shifts = 0;
+
+ errno = 0;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < 2*np_num )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"ismul_np (emushort)" );
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = num;
+#else
+ x = num + np_num - 1;
+#endif
+ if( *x & MASK_SIGN ) sign_num = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = mul;
+#else
+ y = mul + np_num - 1;
+#endif
+ if( *y & MASK_SIGN ) sign_mul = 1;
+
+ /* Allocate memory for ConVerT num ***************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ return;
+ }
+ scvt_s2l_np( pcpy_num, num, np_prod, np_num );
+ /*************************************************************/
+
+ /* Allocate memory for ConVerT mul ***************************/
+ pcpy_mul = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !pcpy_mul )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ return;
+ }
+ scvt_s2l_np( pcpy_mul, mul, np_prod, np_num );
+ /*************************************************************/
+
+ z = prod + np_prod - 1;
+ i = np_prod;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Prod */
+ --z; --i;
+ }
+ ++z; /* z = prod; */
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np_prod );
+ if( sign_mul ) ineg_np( pcpy_mul, pcpy_mul, np_prod );
+
+ x = pcpy_num;
+ y = pcpy_mul;
+
+ k = BITS_PER_EMUSHORT*np_num;
+
+ for( i = 0; i < k; ++i )
+ {
+ if( ORDER_BIT(y,i,np_prod) ) /* см. mpu-emutype.h */
+ {
+ /*
+ следующие операции корректно работают
+ при любом MPU_WORD_ORDER_BIG_ENDIAN
+ */
+ ishln_np( x, x, shifts, np_prod );
+ iadd_np( z, z, x, np_prod ); /* Set Flags */
+
+ shifts = 1;
+ }
+ else ++shifts;
+
+ } /* End if for( i = 0; i < k; ++i ) */
+
+ /* FREE pcpy_mul ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ /* Set RF (major/remainder) flag (with minor sign) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = prod + np_num;
+#else
+ z = prod + np_num - 1;
+#endif
+
+ if( *z & MASK_SIGN ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+
+ i = np_num;
+ while( i > 0 )
+ {
+ if( *z ) major |= 1;
+ else major |= 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( major ) __STR;
+ else __CLR;
+
+ if( sign_num ^ sign_mul ) ineg_np( prod, prod, np_prod );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ /* flags:
+ CF - Carry Flag,
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last iadd_np or ineg_np */
+
+ /* if( OF ) RF (major/remainder) is Not Correct */
+}
+
+#endif /* Use CPU mul/div */
+
+
+#if 1 /* Use CPU mul/div */
+/***************************************************************
+ С использованием операций деления процессора (CPU):
+ ***************************************************************/
+
+/***************************************************************
+ Radix MAX[EMUSHORT] versions of multiply and divide.
+ if BITS_PER_EMUSHORT == 16(от 0 до 65 535),
+ then Radix = 65 536;
+ if BITS_PER_EMUSHORT == 32(от 0 до 4 294 967 295),
+ then Radix = 4 294 967 296;
+ if BITS_PER_EMUSHORT == 64(от 0 до 18 446 744 073 709 551 616),
+ then Radix = 18 446 744 073 709 551 616;
+ etc.
+ ***************************************************************/
+
+#define BASE MASK_CARRY
+
+static void iSINGLE_EMUSHORTm( EMUSHORT *prod, EMUSHORT *num, EMUSHORT mul, int np_prod, int np_num )
+/*******************************************************
+ Multiply integer number NUM
+ by BITS_PER_EMUSHORT-bit quantity MUL,
+ return integer result to PROD.
+ *******************************************************/
+{
+ EMUSHORT *prd = 0, *p, *n;
+ EMULONG carry = 0, tmp;
+ int i;
+
+ if( np_prod < 2 || np_prod > NP_MAX || np_num < 1 || np_prod < np_num+1 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iSINGLE_EMUSHORTm" );
+ return;
+ }
+
+ /*** Allocate memory for prd . ******************************/
+ prd = (EMUSHORT *)__mpu_sbrk( (int)(np_prod*SIZE_OF_EMUSHORT) );
+ if( !prd )
+ {
+ /* fatal error */
+ return;
+ }
+ /************************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = prd;
+#else
+ p = prd + np_prod - 1;
+#endif
+ i = np_prod;
+ while( i > 0 )
+ {
+ *p = 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++p;
+#else
+ --p;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --p; /* младшее слово prd */
+#else
+ ++p; /* младшее слово prd */
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ n = num + np_num - 1; /* младшее слово num */
+#else
+ n = num; /* младшее слово num */
+#endif
+
+ for( i = 0; i < np_num; ++i )
+ {
+ tmp = (EMULONG)*n * (EMULONG)mul + carry;
+ carry = tmp / BASE;
+ *p = (EMUSHORT)(tmp - carry * BASE); /* prd[i] = tmp % BASE; */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --p; --n;
+#else
+ ++p; ++n;
+#endif
+ }
+
+ if( carry )
+ {
+ *p = (EMUSHORT)carry;
+ }
+
+ for( i = 0; i < np_prod; ++i ) prod[i] = prd[i];
+
+ /* FREE prd ***************/
+ __mpu_sbrk( -(int)(np_prod*SIZE_OF_EMUSHORT) );
+ /**************************/
+} /* End of iSINGLE_EMUSHORTm() */
+
+static void iSINGLE_EMUSHORTd( EMUSHORT *quot, EMUSHORT *rem, EMUSHORT *num, EMUSHORT den, int np )
+/******************************************
+ quot - частное
+ rem - остаток (размером в одно слово)
+ num - делимое
+ den - делитель
+ np - размер
+ */
+{
+ EMUSHORT *tquot = 0, *q, *n;
+ EMULONG r = 0, tmp = 0;
+ int i;
+
+ if( !den ) return; /* деление на 0 */
+
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iSINGLE_EMUSHORTd" );
+ return;
+ }
+
+ /*** Allocate memory for tquot . ****************************/
+ tquot = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !tquot )
+ {
+ /* fatal error */
+ return;
+ }
+ /************************************************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ q = tquot + np - 1;
+#else
+ q = tquot;
+#endif
+ i = np;
+ while( i > 0 )
+ {
+ *q = 0;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --q;
+#else
+ ++q;
+#endif
+ --i;
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++q; /* старшее слово tquot */
+#else
+ --q; /* старшее слово tquot */
+#endif
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ n = num; /* старшее слово num */
+#else
+ n = num + np - 1; /* старшее слово num */
+#endif
+
+ for( i = 0; i < np; ++i )
+ {
+ tmp = r * BASE + (EMULONG)(*n);
+ *q = tmp / (EMULONG)den;
+ r = tmp - (EMULONG)(*q) * (EMULONG)den;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++n; ++q;
+#else
+ --n; --q;
+#endif
+ }
+ *rem = r;
+
+ for( i = 0; i < np; ++i ) quot[i] = tquot[i];
+
+ /* FREE tquot *************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /**************************/
+} /* End of iSINGLE_EMUSHORTd() */
+
+
+/***************************************************************
+ Операции беззнакового и знакового деления.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+/******************************************
+ quot - частное
+ rem - остаток
+ num - делимое
+ den - делитель
+ np - размер в EMUSHORT словах
+ */
+void idiv_np( EMUSHORT *quot, EMUSHORT *rem, EMUSHORT *num, EMUSHORT *den, int np )
+{
+ EMUSHORT *z, *r, *x, *y, *p;
+ EMUSHORT *pcpy_num = 0, *pcpy_den = 0;
+ signed int remainder = 0, zero = 1;
+ int b, bnum, bden;
+
+ EMUSHORT scale;
+ int i, j, k, m;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"idiv_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory for Copy num ******************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)((np+1)*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ return;
+ }
+ scpy_s2l_np( pcpy_num, num, np+1, np );
+ /*************************************************************/
+
+ /* Allocate memory for Copy den ******************************/
+ pcpy_den = (EMUSHORT *)__mpu_sbrk( (int)((np+1)*SIZE_OF_EMUSHORT) );
+ if( !pcpy_den )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ return;
+ }
+ scpy_s2l_np( pcpy_den, den, np+1, np );
+ /*************************************************************/
+
+ z = quot + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Quotient */
+ --z; --i;
+ }
+ ++z; /* z = quot; */
+
+ r = rem + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *r = 0; /* bzero Remainder */
+ --r; --i;
+ }
+ ++r; /* r = rem; */
+
+ x = pcpy_num;
+ y = pcpy_den;
+
+ /***************************
+ Размер делимого в словах:
+ ***************************/
+ b = np - 1;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( x[np-b] == 0 && b != (-1) ) --b;
+#else
+ while( x[b] == 0 && b != (-1) ) --b;
+#endif
+ bnum = b; /* b равен индексу наиболее старшего и неравного нулю слова */
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ /***************************
+ Размер делителя в словах:
+ ***************************/
+ b = np - 1;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( y[np-b] == 0 && b != (-1) ) --b;
+#else
+ while( y[b] == 0 && b != (-1) ) --b;
+#endif
+ bden = b; /* b равен индексу наиболее старшего и неравного нулю слова */
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* x = pcpy_num; */
+ /* r = rem = x; */
+ i = np;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *r = *(x+1);
+#else
+ *r = *x;
+#endif
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ /* z = quot */
+ i = np;
+ while( i > 0 )
+ {
+ *z = MASK_ALL_BITS;
+ ++z; --i;
+ }
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STC; __STO; __STS;
+
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ if( bden == 0 )
+ {
+ /************************************************
+ Лишь самое младшее слово делителя неравно нулю,
+ следовательно, здесь можно применить функцию
+ iSINGLE_EMUSHORTd()
+ ************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iSINGLE_EMUSHORTd( z, &r[np-1], x+1, y[np], np );
+#else
+ iSINGLE_EMUSHORTd( z, &r[0], x, y[0], np );
+#endif
+
+ goto check_flags_and_stop;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ /* x = pcpy_num; */
+ /* r = rem = x; */
+ i = np;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *r = *(x+1);
+#else
+ *r = *x;
+#endif
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ m = bnum - bden;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ scale = BASE / (y[np-bden] + 1); /* коэффициент нормализации */
+#else
+ scale = BASE / (y[bden] + 1); /* коэффициент нормализации */
+#endif
+ if( scale > 1 )
+ {
+ /* нормализация */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iSINGLE_EMUSHORTm( x, x+1, scale, np + 1, np );
+ iSINGLE_EMUSHORTm( y, y+1, scale, np + 1, np );
+#else
+ iSINGLE_EMUSHORTm( x, x, scale, np + 1, np );
+ iSINGLE_EMUSHORTm( y, y, scale, np + 1, np );
+#endif
+ }
+
+ /************************************************************
+ Главный цикл шагов деления. Каждая итерация дает очередную
+ цифру частного.
+ K - текущий сдвиг делителя (Y) относительно копии
+ делимого (X), используемый при вычитании, кроме
+ того - индекс очередной цифры частного;
+ J - индекс текущей цифры копии делимого (X).
+ ************************************************************/
+ for( k = m, j = bden + k; k >= 0; --k, --j )
+ {
+ EMULONG guess, rm;
+ EMULONG borrow, carry;
+ EMULONG tmp, tmp1, tmp2;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ guess = ((EMULONG)x[np-j-1] * BASE + (EMULONG)x[np-j]) / (EMULONG)y[np-bden];
+ rm = ((EMULONG)x[np-j-1] * BASE + (EMULONG)x[np-j]) % (EMULONG)y[np-bden];
+#else
+ guess = ((EMULONG)x[j+1] * BASE + (EMULONG)x[j]) / (EMULONG)y[bden];
+ rm = ((EMULONG)x[j+1] * BASE + (EMULONG)x[j]) % (EMULONG)y[bden];
+#endif
+
+ /*********************************************************
+ Пока не будут выполнены условия, уменьшаем частное.
+ *********************************************************/
+ while( rm < BASE )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)y[np-bden+1] * guess;
+ tmp1 = rm * BASE + (EMULONG)x[np-j+1];
+#else
+ tmp2 = (EMULONG)y[bden-1] * guess;
+ tmp1 = rm * BASE + (EMULONG)x[j-1];
+#endif
+ if( (tmp2 > tmp1) || (guess == BASE) )
+ {
+ --guess;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ rm += (EMULONG)y[np-bden];
+#else
+ rm += (EMULONG)y[bden];
+#endif
+ }
+ else
+ break;
+ }
+
+ /*********************************************************
+ Теперь guess - правильное или на единицу большее
+ частное. Вычесть делитель (Y), умноженный на guess из
+ делимого (X), начиная с позиции k + i.
+ *********************************************************/
+ carry = 0; borrow = 0;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = &x[np-k];
+#else
+ p = x + k;
+#endif
+
+ /* Цикл по цифрам делителя (Y). */
+ for( i = 0; i <= bden; ++i )
+ {
+ /* Получить в tmp1 цифру произведения y * guess. */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp1 = (EMULONG)y[np-i] * guess + carry;
+#else
+ tmp1 = (EMULONG)y[i] * guess + carry;
+#endif
+ carry = tmp1 / BASE;
+ tmp1 -= carry * BASE;
+
+ /* Сразу же вычесть из делимого (X). */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)p[-i] - tmp1 - borrow;
+#else
+ tmp2 = (EMULONG)p[i] - tmp1 - borrow;
+#endif
+ if( (tmp2 >> BITS_PER_EMUSHORT) & MASK_SIGN )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2 + BASE;
+#else
+ p[i] = tmp2 + BASE;
+#endif
+ borrow = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2;
+#else
+ p[i] = tmp2;
+#endif
+ borrow = 0;
+ }
+ }
+
+ /*********************************************************
+ Возможно, умноженное на guess число Y удлиннилось.
+ Если это так, то после умножения остался
+ неиспользованный перенос carry. Вычесть и его тоже.
+ *********************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)p[-i] - carry - borrow;
+#else
+ tmp2 = (EMULONG)p[i] - carry - borrow;
+#endif
+ if( (tmp2 >> BITS_PER_EMUSHORT) & MASK_SIGN )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2 + BASE;
+#else
+ p[i] = tmp2 + BASE;
+#endif
+ borrow = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2;
+#else
+ p[i] = tmp2;
+#endif
+ borrow = 0;
+ }
+
+ /* Прошло ли вычитание нормально? */
+ if( borrow == 0 )
+ {
+ /* Да, частное угадано правильно. */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[np-1-k] = guess;
+#else
+ z[k] = guess;
+#endif
+ }
+ else
+ {
+ /******************************************************
+ Нет, последний перенос при вычитании borrow = -1,
+ значит, guess на единицу больше истинного частного.
+ ******************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[np-1-k] = guess - 1;
+#else
+ z[k] = guess - 1;
+#endif
+
+ /* Добавить одно, вычтенное сверх необходимого Y к X. */
+ carry = 0;
+ for( i = 0; i <= bden; ++i )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp = (EMULONG)p[-i] + (EMULONG)y[np-i] + carry;
+#else
+ tmp = (EMULONG)p[i] + (EMULONG)y[i] + carry;
+#endif
+ if( tmp >= BASE )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp - BASE;
+#else
+ p[i] = tmp - BASE;
+#endif
+ carry = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp;
+#else
+ p[i] = tmp;
+#endif
+ carry = 0;
+ }
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = (EMULONG)p[-i] + carry - BASE;
+#else
+ p[i] = (EMULONG)p[i] + carry - BASE;
+#endif
+ }
+
+ } /* End for( k = m, j = bden + k; k >= 0; --k, --j ) */
+
+ /* Деление завершено. */
+
+ /************************************************************
+ Если происходила нормализация - разделить на нормализующий
+ множитель. То, что остадось от делимого (X) - остаток.
+ ************************************************************/
+ if( scale > 1 )
+ {
+ EMUSHORT junk;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ /* iSINGLE_EMUSHORTd( y+1, &junk, y+1, scale, np ); */
+ iSINGLE_EMUSHORTd( rem, &junk, x+1, scale, np );
+#else
+ /* iSINGLE_EMUSHORTd( y, &junk, y, scale, np ); */
+ iSINGLE_EMUSHORTd( rem, &junk, x, scale, np );
+#endif
+ }
+ else
+ {
+ for( i = 0; i < np; ++i )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ rem[i] = x[i+1];
+#else
+ rem[i] = x[i];
+#endif
+ }
+ }
+
+ /************************************************************
+ CHECK FLAGS:
+ ************************************************************/
+check_flags_and_stop:
+
+ /* z = quot; */
+
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLP;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ /* z = (high part of)quot */
+ if( *z & MASK_SIGN ) __STS;
+#else
+ /* z = (low part of)quot */
+ if( z[np-1] & MASK_SIGN ) __STS;
+#endif
+ else __CLS;
+
+ i = np;
+ while( i > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+ ++z; --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+ __CLV; /* VF (invalid) flag */
+
+ /* r = rem; */
+ i = np;
+ while( i > 0 )
+ {
+ if( *r ) remainder |= 1;
+ ++r; --i;
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+} /* End of idiv_np() */
+
+void isdiv_np( EMUSHORT *quot, EMUSHORT *rem, EMUSHORT *num, EMUSHORT *den, int np )
+{
+ EMUSHORT *z, *r, *x, *y, *p, sj = 0;
+ EMUSHORT *pcpy_num = 0, *pcpy_den = 0;
+ signed int sign_num = 0, sign_den = 0;
+ signed int remainder = 0, zero = 1;
+ int b, bnum, bden;
+
+ EMUSHORT scale;
+ int i, j, k, m;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isdiv_np (emushort)" );
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = num;
+#else
+ x = num + np - 1;
+#endif
+ if( *x & MASK_SIGN ) sign_num = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = den;
+#else
+ y = den + np - 1;
+#endif
+ if( *y & MASK_SIGN ) sign_den = 1;
+
+ /* Allocate memory for Copy num ******************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)((np+1)*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ return;
+ }
+ scvt_s2l_np( pcpy_num, num, np+1, np );
+ /*************************************************************/
+
+ /* Allocate memory for Copy den ******************************/
+ pcpy_den = (EMUSHORT *)__mpu_sbrk( (int)((np+1)*SIZE_OF_EMUSHORT) );
+ if( !pcpy_den )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ return;
+ }
+ scvt_s2l_np( pcpy_den, den, np+1, np );
+ /*************************************************************/
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np+1 );
+ if( sign_den ) ineg_np( pcpy_den, pcpy_den, np+1 );
+
+ z = quot + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Quotient */
+ --z; --i;
+ }
+ ++z; /* z = quot; */
+
+ r = rem + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *r = 0; /* bzero Remainder */
+ --r; --i;
+ }
+ ++r; /* r = rem; */
+
+ x = pcpy_num;
+ y = pcpy_den;
+
+ /***************************
+ Размер делимого в словах:
+ ***************************/
+ b = np - 1;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( x[np-b] == 0 && b != (-1) ) --b;
+#else
+ while( x[b] == 0 && b != (-1) ) --b;
+#endif
+ bnum = b; /* b равен индексу наиболее старшего и неравного нулю слова */
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ /***************************
+ Размер делителя в словах:
+ ***************************/
+ b = np - 1;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ while( y[np-b] == 0 && b != (-1) ) --b;
+#else
+ while( y[b] == 0 && b != (-1) ) --b;
+#endif
+ bden = b; /* b равен индексу наиболее старшего и неравного нулю слова */
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np+1 );
+ /* x = pcpy_num; */
+ /* r = rem = x; */
+ i = np;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *r = *(x+1);
+#else
+ *r = *x;
+#endif
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( !sign_num ) sj = MASK_ALL_BITS;
+
+ /* z = quot */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1;
+#endif
+ /* z = (low part of)quot */
+ i = np;
+ while( i > 0 )
+ {
+ *z = sj;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( !sign_num )
+ {
+ *z ^= MASK_SIGN;
+ __CLS; /* Sign Flag */
+ }
+ else
+ {
+ *z |= MASK_SIGN;
+ __STS; /* Sign Flag */
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STC; __STO;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ if( bden == 0 )
+ {
+ /************************************************
+ Лишь самое младшее слово делителя неравно нулю,
+ следовательно, здесь можно применить функцию
+ iSINGLE_EMUSHORTd()
+ ************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iSINGLE_EMUSHORTd( z, &r[np-1], x+1, y[np], np );
+#else
+ iSINGLE_EMUSHORTd( z, &r[0], x, y[0], np );
+#endif
+
+ goto check_flags_and_stop;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ x = pcpy_num;
+ /* r = rem = x; */
+ i = np;
+ while( i > 0 )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *r = *(x+1);
+#else
+ *r = *x;
+#endif
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( sign_num ^ sign_den ) ineg_np( rem, rem, np );
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ m = bnum - bden;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ scale = BASE / (y[np-bden] + 1); /* коэффициент нормализации */
+#else
+ scale = BASE / (y[bden] + 1); /* коэффициент нормализации */
+#endif
+ if( scale > 1 )
+ {
+ /* нормализация */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iSINGLE_EMUSHORTm( x, x+1, scale, np + 1, np );
+ iSINGLE_EMUSHORTm( y, y+1, scale, np + 1, np );
+#else
+ iSINGLE_EMUSHORTm( x, x, scale, np + 1, np );
+ iSINGLE_EMUSHORTm( y, y, scale, np + 1, np );
+#endif
+ }
+
+
+ /************************************************************
+ Главный цикл шагов деления. Каждая итерация дает очередную
+ цифру частного.
+ K - текущий сдвиг делителя (Y) относительно копии
+ делимого (X), используемый при вычитании, кроме
+ того - индекс очередной цифры частного;
+ J - индекс текущей цифры копии делимого (X).
+ ************************************************************/
+ for( k = m, j = bden + k; k >= 0; --k, --j )
+ {
+ EMULONG guess, rm;
+ EMULONG borrow, carry;
+ EMULONG tmp, tmp1, tmp2;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ guess = ((EMULONG)x[np-j-1] * BASE + (EMULONG)x[np-j]) / (EMULONG)y[np-bden];
+ rm = ((EMULONG)x[np-j-1] * BASE + (EMULONG)x[np-j]) % (EMULONG)y[np-bden];
+#else
+ guess = ((EMULONG)x[j+1] * BASE + (EMULONG)x[j]) / (EMULONG)y[bden];
+ rm = ((EMULONG)x[j+1] * BASE + (EMULONG)x[j]) % (EMULONG)y[bden];
+#endif
+
+ /*********************************************************
+ Пока не будут выполнены условия, уменьшаем частное.
+ *********************************************************/
+ while( rm < BASE )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)y[np-bden+1] * guess;
+ tmp1 = rm * BASE + (EMULONG)x[np-j+1];
+#else
+ tmp2 = (EMULONG)y[bden-1] * guess;
+ tmp1 = rm * BASE + (EMULONG)x[j-1];
+#endif
+ if( (tmp2 > tmp1) || (guess == BASE) )
+ {
+ --guess;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ rm += (EMULONG)y[np-bden];
+#else
+ rm += (EMULONG)y[bden];
+#endif
+ }
+ else
+ break;
+ }
+
+ /*********************************************************
+ Теперь guess - правильное или на единицу большее
+ частное. Вычесть делитель (Y), умноженный на guess из
+ делимого (X), начиная с позиции k + i.
+ *********************************************************/
+ carry = 0; borrow = 0;
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p = &x[np-k];
+#else
+ p = x + k;
+#endif
+
+ /* Цикл по цифрам делителя (Y). */
+ for( i = 0; i <= bden; ++i )
+ {
+ /* Получить в tmp1 цифру произведения y * guess. */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp1 = (EMULONG)y[np-i] * guess + carry;
+#else
+ tmp1 = (EMULONG)y[i] * guess + carry;
+#endif
+ carry = tmp1 / BASE;
+ tmp1 -= carry * BASE;
+
+ /* Сразу же вычесть из делимого (X). */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)p[-i] - tmp1 - borrow;
+#else
+ tmp2 = (EMULONG)p[i] - tmp1 - borrow;
+#endif
+ if( (tmp2 >> BITS_PER_EMUSHORT) & MASK_SIGN )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2 + BASE;
+#else
+ p[i] = tmp2 + BASE;
+#endif
+ borrow = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2;
+#else
+ p[i] = tmp2;
+#endif
+ borrow = 0;
+ }
+ }
+
+ /*********************************************************
+ Возможно, умноженное на guess число Y удлиннилось.
+ Если это так, то после умножения остался
+ неиспользованный перенос carry. Вычесть и его тоже.
+ *********************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp2 = (EMULONG)p[-i] - carry - borrow;
+#else
+ tmp2 = (EMULONG)p[i] - carry - borrow;
+#endif
+ if( (tmp2 >> BITS_PER_EMUSHORT) & MASK_SIGN )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2 + BASE;
+#else
+ p[i] = tmp2 + BASE;
+#endif
+ borrow = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp2;
+#else
+ p[i] = tmp2;
+#endif
+ borrow = 0;
+ }
+
+ /* Прошло ли вычитание нормально? */
+ if( borrow == 0 )
+ {
+ /* Да, частное угадано правильно. */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[np-1-k] = guess;
+#else
+ z[k] = guess;
+#endif
+ }
+ else
+ {
+ /******************************************************
+ Нет, последний перенос при вычитании borrow = -1,
+ значит, guess на единицу больше истинного частного.
+ ******************************************************/
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[np-1-k] = guess - 1;
+#else
+ z[k] = guess - 1;
+#endif
+
+ /* Добавить одно, вычтенное сверх необходимого Y к X. */
+ carry = 0;
+ for( i = 0; i <= bden; ++i )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ tmp = (EMULONG)p[-i] + (EMULONG)y[np-i] + carry;
+#else
+ tmp = (EMULONG)p[i] + (EMULONG)y[i] + carry;
+#endif
+ if( tmp >= BASE )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp - BASE;
+#else
+ p[i] = tmp - BASE;
+#endif
+ carry = 1;
+ }
+ else
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = tmp;
+#else
+ p[i] = tmp;
+#endif
+ carry = 0;
+ }
+ }
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ p[-i] = (EMULONG)p[-i] + carry - BASE;
+#else
+ p[i] = (EMULONG)p[i] + carry - BASE;
+#endif
+ }
+
+ } /* End for( k = m, j = bden + k; k >= 0; --k, --j ) */
+
+ /* Деление завершено. */
+
+ /************************************************************
+ Если происходила нормализация - разделить на нормализующий
+ множитель. То, что остадось от делимого (X) - остаток.
+ ************************************************************/
+ if( scale > 1 )
+ {
+ EMUSHORT junk;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ /* iSINGLE_EMUSHORTd( y+1, &junk, y+1, scale, np ); */
+ iSINGLE_EMUSHORTd( rem, &junk, x+1, scale, np );
+#else
+ /* iSINGLE_EMUSHORTd( y, &junk, y, scale, np ); */
+ iSINGLE_EMUSHORTd( rem, &junk, x, scale, np );
+#endif
+ }
+ else
+ {
+ for( i = 0; i < np; ++i )
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ rem[i] = x[i+1];
+#else
+ rem[i] = x[i];
+#endif
+ }
+ }
+
+ /************************************************************
+ CHECK FLAGS:
+ ************************************************************/
+check_flags_and_stop:
+
+ /* r = rem; */
+ i = np;
+ while( i > 0 )
+ {
+ if( *r ) remainder |= 1;
+ ++r; --i;
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ if( sign_num ^ sign_den )
+ {
+ ineg_np( rem, rem, np );
+ ineg_np( quot, quot, np );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+
+ if( __MFLAG(SF) == (sign_num ^ sign_den) )
+ /* if( Correct result Sign ) */
+ __CLO; /* Overflow Flag */
+
+ /* flags:
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last ineg_np() */
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ /* z = quot */
+
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLP;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ /* z = (high part of)quot */
+ if( *z & MASK_SIGN ) __STS;
+#else
+ /* z = (low part of)quot */
+ if( z[np-1] & MASK_SIGN ) __STS;
+#endif
+ else __CLS;
+
+ i = np;
+ while( i > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+ ++z; --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+ /* т.к. здесь идет речь о положительных числах
+ (именно в их знаковом представлении 011111)
+ наличие 1 в старшем разряде недопустимо */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+ __CLV; /* VF (invalid) flag */
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)((np+1)*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+} /* End of isdiv_np() */
+
+#undef BASE
+
+#else /* Do not use CPU mul/div */
+/***************************************************************
+ Без использования операций деления процессора (CPU):
+ ***************************************************************/
+
+/***************************************************************
+ Операции беззнакового и знакового деления.
+ Изменяет флаги: CF, AF=0, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+
+void idiv_np( EMUSHORT *quot, EMUSHORT *rem, EMUSHORT *num, EMUSHORT *den, int np )
+{
+ EMUSHORT *z, *r, *x, *y, j;
+ EMUSHORT *pcpy_num = 0, *pcpy_den = 0;
+ signed int remainder = 0, zero = 1;
+ signed int i, k;
+ int b, bnum, bden;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"idiv_np (emushort)" );
+ return;
+ }
+
+ /* Allocate memory for Copy num ******************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ return;
+ }
+ scpy_s2s_np( pcpy_num, num, np );
+ /*************************************************************/
+
+ /* Allocate memory for Copy den ******************************/
+ pcpy_den = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !pcpy_den )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ return;
+ }
+ scpy_s2s_np( pcpy_den, den, np );
+ /*************************************************************/
+
+ z = quot + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Quotient */
+ --z; --i;
+ }
+ ++z; /* z = quot; */
+
+ r = rem + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *r = 0; /* bzero Remainder */
+ --r; --i;
+ }
+ ++r; /* r = rem; */
+
+ x = pcpy_num;
+ y = pcpy_den;
+
+ b = np * BITS_PER_EMUSHORT - 1;
+ while( !ORDER_BIT(x,b,np) && b != (-1) ) --b;
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ b = np * BITS_PER_EMUSHORT - 1;
+ while( !ORDER_BIT(y,b,np) && b != (-1) ) --b;
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* x = pcpy_num; */
+ /* r = rem */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ /* z = quot */
+ i = np;
+ while( i > 0 )
+ {
+ *z = MASK_ALL_BITS;
+ ++z; --i;
+ }
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STC; __STO; __STS;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ /* x = pcpy_num; */
+ /* r = rem */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_np( y, y, k, np ); /* value(k) my be zero */
+
+ ++k;
+
+ /* z = quot; */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)quot */
+#endif
+ for( i = 0; i < k; ++i )
+ {
+ icmp_np( x, y, np );
+ if( !__MFLAG(SF) )
+ {
+ isub_np( x, x, y, np );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_np( quot, quot, np ); /* shift to 1 */
+ *z |= j;
+
+ ishr_np( y, y, np );
+ }
+
+ /* z = (low part of)quot */
+
+ /* PF (parity) не определяем. Сбрасываем */
+
+ i = np;
+ while( i > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ /* z = (high part of)quot */
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+ __CLV; /* VF (invalid) flag */
+
+ /* copy pcpy_num to rem */
+ /* r = rem; */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+}
+
+void isdiv_np( EMUSHORT *quot, EMUSHORT *rem, EMUSHORT *num, EMUSHORT *den, int np )
+{
+ EMUSHORT *z, *r, *x, *y, j = 0;
+ EMUSHORT *pcpy_num = 0, *pcpy_den = 0;
+ signed int sign_num = 0, sign_den = 0;
+ signed int remainder = 0, zero = 1;
+ signed int i, k;
+ int b, bnum, bden;
+
+ errno = 0;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"isdiv_np (emushort)" );
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = num;
+#else
+ x = num + np - 1;
+#endif
+ if( *x & MASK_SIGN ) sign_num = 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ y = den;
+#else
+ y = den + np - 1;
+#endif
+ if( *y & MASK_SIGN ) sign_den = 1;
+
+ /* Allocate memory for ConVerT num ***************************/
+ pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !pcpy_num )
+ {
+ /* fatal error */
+ return;
+ }
+ scpy_s2s_np( pcpy_num, num, np );
+ /*************************************************************/
+
+ /* Allocate memory for ConVerT den ***************************/
+ pcpy_den = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !pcpy_den )
+ {
+ /* fatal error */
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ return;
+ }
+ scpy_s2s_np( pcpy_den, den, np );
+ /*************************************************************/
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np );
+ if( sign_den ) ineg_np( pcpy_den, pcpy_den, np );
+
+ z = quot + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Quotient */
+ --z; --i;
+ }
+ ++z; /* z = quot; */
+
+ r = rem + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *r = 0; /* bzero Remainder */
+ --r; --i;
+ }
+ ++r; /* r = rem; */
+
+ x = pcpy_num;
+ y = pcpy_den;
+
+ b = np * BITS_PER_EMUSHORT - 1;
+ while( !ORDER_BIT(x,b,np) && b != (-1) ) --b;
+ bnum = b;
+
+ if( bnum == -1 )
+ {
+ /* dividend == 0 (делимое == 0); ==> qout = 0; rem = 0; */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ b = np * BITS_PER_EMUSHORT - 1;
+ while( !ORDER_BIT(y,b,np) && b != (-1) ) --b;
+ bden = b;
+
+ if( bden == -1 )
+ {
+ /* DIVISION BY ZERO */
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( sign_num ) ineg_np( pcpy_num, pcpy_num, np );
+ /* x = pcpy_num; */
+ /* r = rem */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( !sign_num ) j = MASK_ALL_BITS;
+
+ /* z = quot */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1;
+#endif
+ /* z = (low part of)quot */
+ i = np;
+ while( i > 0 )
+ {
+ *z = j;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( !sign_num )
+ {
+ *z ^= MASK_SIGN;
+ __CLS; /* Sign Flag */
+ }
+ else
+ {
+ *z |= MASK_SIGN;
+ __STS; /* Sign Flag */
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STC; __STO;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ if( bnum < bden )
+ {
+ /* num < den; ==> qout = 0; */
+
+ x = pcpy_num;
+ /* r = rem */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( sign_num ^ sign_den ) ineg_np( rem, rem, np );
+
+ /* AF (aux carry) не определяем. Сбрасываем */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLEAR_IFLAGS;
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ __STZ;
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ k = bnum - bden;
+
+ ishln_np( y, y, k, np ); /* value(k) my be zero */
+
+ ++k;
+
+ /* z = quot */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1;
+#endif
+ /* z = (low part of)quot */
+ for( i = 0; i < k; ++i )
+ {
+ icmp_np( x, y, np );
+ if( !__MFLAG(SF) )
+ {
+ isub_np( x, x, y, np );
+ j = 1;
+ }
+ else j = 0;
+
+ ishl_np( quot, quot, np ); /* shift to 1 */
+ *z |= j;
+
+ ishr_np( y, y, np );
+ }
+
+
+ /* copy pcpy_num to rem */
+ /* x = pcpy_num */
+ /* r = rem; */
+ i = np;
+ while( i > 0 )
+ {
+ *r = *x;
+
+ if( *r ) remainder |= 1;
+
+ ++x; ++r;
+ --i;
+ }
+
+ if( remainder ) __STR; /* RF=1, if(rem != 0) */
+ else __CLR;
+
+ if( sign_num ^ sign_den )
+ {
+ ineg_np( rem, rem, np );
+ ineg_np( quot, quot, np );
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+
+ if( __MFLAG(SF) == (sign_num ^ sign_den) )
+ /* if( Correct result Sign ) */
+ __CLO; /* Overflow Flag */
+
+ /* flags:
+ OF - Overflow Flag,
+ SF - Sign Flag,
+ PF - Parity Flag,
+ ZF - Zero Flag,
+ VF - Invalid Flag
+ are Correct after last ineg_np() */
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+
+ return;
+ }
+
+ /* z = (low part of)quot */
+ /* PF (parity) не определяем. Сбрасываем */
+ __CLP;
+
+ i = np;
+ while( i > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --i;
+ }
+
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ if( __MFLAG(SF) ) __STO; /* warning */
+ else __CLO;
+ /* т.к. здесь идет речь о положительных числах
+ (именно в их знаковом представлении 011111)
+ наличие 1 в старшем разряде недопустимо */
+
+ __CLA; /* AF (aux carry) не определяем. Сбрасываем */
+ __CLC; /* CF (carry) flag */
+ __CLV; /* VF (invalid) flag */
+
+ /* FREE pcpy_num ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+ /* FREE pcpy_den ***************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /*******************************/
+}
+
+#endif /* Use CPU mul/div */
+
+
+/***************************************************************
+ Операции преобразования целых чисел в строку и обратно.
+ ***************************************************************/
+
+/***************************************************************
+ NOTE:
+ ====
+ Числа, в виде строки, могут быть представлены следующим
+ образом:
+
+ 0b111111
+ 0B111111 - двоичное число; разряды содержат
+ символы '0' или '1'; префикс 0b или
+ 0B.
+
+ 01234567 - восьмеричное число; разряды содержат
+ символы ['0'-'7']; число начинается
+ с '0'.
+
+ 0x123456789abcdef
+ 0X123456789ABCDEF - шестнадцатеричное число; разряды
+ содержат символы ['0'-'9'] и ['a'-'f']
+ в любом регистре; префикс 0x или 0X.
+ (0X123456789aBcDeF - смесь
+ допускается.)
+
+ 1234567890 - десятичное число; разряды содержат
+ символы ['0'-'9']; число не может
+ начинаться с символа '0'; допускаются
+ знаки '+', '-' перед числом.
+
+ Функции переводящие строку символов в число воспринимают
+ числа, представленные строкой, согласно префиксу и
+ переводят ее в целое, заданной длины; если число не
+ умещается в заданный формат - выставляется флаг
+ переполнения (OF).
+ =============================
+
+ Функции, переводящие число в строку, могут выводить число
+ символов равное количеству бит исходного формата плюс два
+ (max-префикс[2] и естественно завершающий + '\0').
+ ЕСЛИ ПОЛЬЗОВАТЕЛЬ ОТДАЛ ФУНКЦИИ УКАЗАТЕЛЬ НА СТРОКУ
+ МЕНЬШЕГО РАЗМЕРА ЧЕМ НЕОБХОДИМО ТО РЕЗУЛЬТАТ ОПРЕДЕЛЯЕТСЯ
+ РЕАКЦИЕЙ СИСТЕМНОЙ ФУНКЦИИ strcpy( char *, char * )
+ НА ТАКОГО РОДА ОШИБКУ.
+
+ Данные функции имеют дополнительный параметр radix,
+ который может быть равен 2, 8. 10 или 16 и по нему будет
+ установлен соответствующий префикс.
+
+ Вообще, число может сопровождаться суффиксом:
+
+ i128 - целое со знаком 128 бит (int128)
+ ui128 - целое без знака 128 бит (unsigned int128)
+
+ I128 - целое со знаком 128 бит
+ UI128 - целое без знака 128 бит
+
+ u - целое без знака зависимое от машины (int)
+ U - целое без знака зависимое от машины (int)
+ l - целое со знаком зависимое от машины (long int)
+ L - целое со знаком зависимое от машины (long int)
+
+ и естественно ul, Ul, uL, UL.
+
+ ==========================================================
+ = Описываемые ниже функции не читают суффиксы и требуют =
+ = от пользователя задавать правильный размер числа; =
+ ==========================================================
+ При записи строки суффиксы тоже не добавляются.
+
+
+ ПЕРЕВОД СТРОКИ В ЧИСЛО
+ ======================
+
+ Для функций перевода строки в число исходная строка должна
+ иметь форму:
+
+ [пробелы][знак][пробелы][префикс][цифры]
+
+ к пробелам относятся: ' ', '\n', '\t', '\v', '\r'.
+ знак: '+', '-'.
+ префикс: 0b, 0B, 0, 0x, 0X.
+ цифры: 1234567890 abcdef (ABCDEF).
+
+ Функции пропускают пробельные символы, анализируют знак,
+ если после знака есть пробелы, то они игнорируются и, после
+ этого, начинается разбор числа. После анализа префикса
+ становится ясно в какой системе счисления представлено
+ число. Если имеет место двоичное, восьмеричное или
+ шестнадцатеричное представление, то считанный ранее знак
+ просто игнорируется (ПОЛЬЗОВАТЕЛЮ СЛЕДУЕТ ОБРАТИТЬ ВНИМАНИЕ
+ НА ДАННОЕ ОБСТОЯТЕЛЬСТВО), число воспринимается как
+ беззнаковое.
+ Если все значащие биты числа, представленного в строке, не
+ удается разместить в приемнике, то выставляется флаг OF и
+ работа функции завершается без дополнительных
+ предупреждений.
+
+ После данных операций выставляются флаги PF, ZF, SF
+ согласно результату, флаги AF, CF сбрасываются в 0, а флаг
+ OF сигнализирует о наличии или отсутствии переполнения.
+ Флаг RF не изменяется.
+
+ Примеры:
+
+ перевод строки в байт
+
+ "+0377" --> 11 111 111 OF=0, SF=1, PF=0, ZF=0.
+ "-0477" --> 00 111 111 OF=1, SF=0, PF=0, ZF=0.
+
+ знак здесь игнорируется, и так как для числа из второго
+ примера необходимо 9 бит, выставляется флаг OF=1.
+ Результирующий знак определяется самим числом!
+
+ "+15" --> 0000 1111 OF=0, SF=0, PF=0, ZF=0.
+ "-8" --> 1111 1000 OF=0, SF=1, PF=1, ZF=0.
+
+ "+0xff" --> 1111 1111 OF=0, SF=1, PF=0, ZF=0.
+
+ По отношению к bin, oct, hex числам Знаковые и Беззнаковые
+ функции действуют одинаково.
+ По отношению к десятичным числам знаковые и беззнаковые
+ функции отличаются, например:
+
+ знаковый перевод (iATOI...)
+
+ "+128" --> 1000 0000 OF=1, т.к. 8-битное число
+ ограничено пределом +127.
+
+ беззнаковый перевод (iATOUI...)
+
+ "+128" --> 1000 0000 OF=0, т.к. беззнаковое
+ 8-битное целое не ограничено
+ числом 128.
+
+
+ Строка читается до тех пор пока не будет обнаружен
+ символ, который нельзя отнести к числу. Если до этого
+ не было цифр то в приемник будет записан 0.
+
+
+ ПЕРЕВОД ЧИСЛА В СТРОКУ
+ ======================
+
+ Флаги не выставляются и не изменяются!
+
+ Выводится префикс и число.
+ для dес. чисел существует знаковый (iITOA...)
+ и беззнаковый (iUITOA...) перевод
+
+ 1000 0000 --> "-128" знаковый
+ 1000 0000 --> "128" беззнаковый
+
+ 1111 1111 --> "-1" знаковый
+ 1111 1111 --> "255" беззнаковый
+
+ Числа 0b, 0, 0x выводятся без знака
+
+ 1111 1111 --> "0377" если radix=8
+ 1111 1111 --> "0xff" если radix=16
+ 1111 1111 --> "0b11111111" если radix=2
+
+ Если число равно 0, то будет выведен
+ "0" (radix = 8 or 10);
+ "0x0" (radix = 16);
+ "0b0" (radix = 2).
+
+ Еще один параметр функций - uf если он равен
+ единице uf = 1, то буквы префикса и числа будут
+ выводиться в верхнем регистре, если он равен нулю
+ uf = 0, то в нижнем
+
+ pref=1 ---> "0XFF"
+ pref=0 ---> "0xff"
+
+ ***************************************************************/
+
+/***************************************************************
+ Операции преобразования символьных строк в целые числа.
+ Изменяет флаги: CF=0, AF=0, PF, ZF, SF, OF.
+ Не изменяет: RF.
+ ***************************************************************/
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+#define _IS_SPACE_(c) ( (c) == NEWLINE || \
+ (c) == CR || \
+ (c) == SP || \
+ (c) == HT || \
+ (c) == VT )
+
+#define _IS_DIGIT_(c) (((c) >= '0')&&((c) <= '9'))
+
+#define _IS_XDIGIT_(c) ( (((c) >= '0')&&((c) <= '9')) || \
+ (((c) >= 'A')&&((c) <= 'F')) || \
+ (((c) >= 'a')&&((c) <= 'f')) )
+
+static int hexval( int c )
+{
+ if( c >= '0' && c <= '9' ) return ( c - '0' );
+ if( c >= 'A' && c <= 'F' ) return ( c - 'A' + 10 );
+ if( c >= 'a' && c <= 'f' ) return ( c - 'a' + 10 );
+
+ return( -1 );
+}
+
+/*******************************************************
+ Функции:
+ sATOI_..._10();
+ sATOI_..._16();
+ sATOI_..._8();
+ sATOI_..._2();
+ получают указатель на не пустую строку без префикса
+ (0b, 0B, 0, 0x или 0X), содержащую только цифры:
+ 0123456789abcdef (или ABCDEF) (пробелы перед цифрами
+ не допускаются).
+
+ sATOI_..._10(); - читает число пока не встретит
+ символ который нельзя отнести
+ к набору десятичных чисел
+ [0123456789].
+ sATOI_..._16(); - читает число пока не встретит
+ символ который нельзя отнести
+ к набору шестнадцатиричных чисел
+ [0123456789abcdef(ABCDEF)].
+ sATOI_..._8(); - читает число пока не встретит
+ символ который нельзя отнести
+ к набору восмеричных чисел
+ [01234567].
+ sATOI_..._2(); - читает число пока не встретит
+ символ который нельзя отнести
+ к набору двоичных чисел
+ [01].
+ *******************************************************/
+static void satoi8_10( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint8_t b, weight = 10;
+ __mpu_uint16_t tmp = 0, mul = 1;
+ __mpu_char8_t *ptr;
+ signed int save_RF;
+ signed int i = 0; /* number of digits */
+
+ __CLV;
+
+ save_RF = __MFLAG(RF); /* save RF */
+
+ ptr = str;
+
+ while( _IS_DIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint8_t) *ptr;
+ b -= '0';
+
+ icpy_s2l_8to16( (__mpu_uint16_t *)&tmp, &b );
+ imul_8( (__mpu_uint16_t *)&tmp, (__mpu_uint8_t *)&tmp, (__mpu_uint8_t *)&mul );
+
+ if( !__MFLAG(RF) ) /* high part of tmp[] is null */
+ {
+ iadd_8( c, c, (__mpu_uint8_t *)&tmp );
+
+ if( __MFLAG(CF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+ }
+ else
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ imul_8( (__mpu_uint16_t *)&mul, (__mpu_uint8_t *)&mul, &weight );
+
+ --i;
+ --ptr;
+
+ if( i && __MFLAG(RF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+}
+
+static void satoi8_16( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint8_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( _IS_XDIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > 2 )
+ {
+ __STO; /* Overflow Flag */
+ i = 2;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint8_t) *ptr;
+ b = (__mpu_uint8_t) hexval( b );
+
+ *c |= b << (k*4);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi8_8( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint8_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr >= '0' && *ptr <= '7' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i >= 3 )
+ {
+ b = (__mpu_uint8_t) *(ptr - 2);
+ b -= '0';
+
+ if( b > 3 || i > 3 )
+ {
+ __STO; /* Overflow Flag */
+ }
+ i = 3;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint8_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k*3);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi8_2( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint8_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr == '0' || *ptr == '1' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > BITS_PER_BYTE )
+ {
+ __STO; /* Overflow Flag */
+ i = BITS_PER_BYTE;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint8_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+/* от -128 до +127 */
+void iatoi_8( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ signed int sign = 0, save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' )
+ {
+ if( *ptr == '-' ) sign = 1;
+ ++ptr;
+ }
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoi_8" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi8_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi8_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi8_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi8_10( c, ptr );
+ if( __MFLAG(OF) ) return;
+
+ if( sign ) ineg_8( c, c );
+ if( sign == __MFLAG(SF) ) __CLO;
+ else __STO;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ return;
+ }
+}
+
+/* от 0 до +255 */
+void iatoui_8( __mpu_uint8_t *c, __mpu_char8_t *str )
+{
+ signed int save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' ) ++ptr;
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoui_8" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi8_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi8_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi8_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi8_10( c, ptr );
+ return;
+ }
+}
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static void satoi16_10( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint16_t b, weight = 10;
+ __mpu_uint32_t tmp = 0, mul = 1;
+ __mpu_char8_t *ptr;
+ signed int save_RF;
+ signed int i = 0; /* number of digits */
+
+ __CLV;
+
+ save_RF = __MFLAG(RF); /* save RF */
+
+ ptr = str;
+
+ while( _IS_DIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint16_t) *ptr;
+ b -= '0';
+
+ icpy_s2l_16to32( &tmp, &b );
+ imul_16( &tmp, (__mpu_uint16_t *)&tmp, (__mpu_uint16_t *)&mul );
+
+ if( !__MFLAG(RF) ) /* high part of tmp[] is null */
+ {
+ iadd_16( c, c, (__mpu_uint16_t *)&tmp );
+
+ if( __MFLAG(CF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ }
+ else
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ imul_16( &mul, (__mpu_uint16_t *)&mul, &weight );
+
+ --i;
+ --ptr;
+
+ if( i && __MFLAG(RF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+}
+
+static void satoi16_16( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint16_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( _IS_XDIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > 4 )
+ {
+ __STO; /* Overflow Flag */
+ i = 4;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint16_t) *ptr;
+ b = (__mpu_uint16_t) hexval( b );
+
+ *c |= b << (k*4);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi16_8( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint16_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr >= '0' && *ptr <= '7' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i >= 6 )
+ {
+ b = (__mpu_uint16_t) *(ptr - 5);
+ b -= '0';
+
+ if( b > 1 || i > 6 )
+ {
+ __STO; /* Overflow Flag */
+ }
+ i = 6;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint16_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k*3);
+
+ --i;
+ --ptr;
+ ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi16_2( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint16_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr == '0' || *ptr == '1' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > BITS_PER_TWO_BYTES )
+ {
+ __STO; /* Overflow Flag */
+ i = BITS_PER_TWO_BYTES;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint16_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k);
+
+ --i;
+ --ptr;
+ ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x8000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+/* от -32768 до +32767 */
+void iatoi_16( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ signed int sign = 0, save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' )
+ {
+ if( *ptr == '-' ) sign = 1;
+ ++ptr;
+ }
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoi_16" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi16_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi16_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi16_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi16_10( c, ptr );
+ if( __MFLAG(OF) ) return;
+
+ if( sign ) ineg_16( c, c );
+ if( sign == __MFLAG(SF) ) __CLO;
+ else __STO;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ return;
+ }
+}
+
+
+/* от 0 до +65535 */
+void iatoui_16( __mpu_uint16_t *c, __mpu_char8_t *str )
+{
+ signed int save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' ) ++ptr;
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoui_16" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi16_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi16_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi16_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi16_10( c, ptr );
+ return;
+ }
+}
+
+
+#define BITS_PER_EIGHT_BYTES 64
+
+#if BITS_PER_EMUSHORT > 32
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static void satoi32_10( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint32_t b, weight = 10;
+ __mpu_uint64_t tmp = 0, mul = 1;
+ __mpu_char8_t *ptr;
+ signed int save_RF;
+ signed int i = 0; /* number of digits */
+
+ __CLV;
+
+ save_RF = __MFLAG(RF); /* save RF */
+
+ ptr = str;
+
+ while( _IS_DIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint32_t) *ptr;
+ b -= '0';
+
+ icpy_s2l_32to_np( (EMUSHORT *)&tmp, &b, BITS_PER_EIGHT_BYTES/
+ BITS_PER_EMUSHORT /* == 1 */ );
+ imul_32( &tmp, (__mpu_uint32_t *)&tmp, (__mpu_uint32_t *)&mul );
+
+ if( !__MFLAG(RF) ) /* high part of tmp[] is null */
+ {
+ iadd_32( c, c, (__mpu_uint32_t *)&tmp );
+
+ if( __MFLAG(CF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ }
+ else
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ imul_32( &mul, (__mpu_uint32_t *)&mul, &weight );
+
+ --i;
+ --ptr;
+
+ if( i && __iflag_major_rem )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+}
+
+static void satoi32_16( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint32_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( _IS_XDIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > 8 )
+ {
+ __STO; /* Overflow Flag */
+ i = 8;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint32_t) *ptr;
+ b = (__mpu_uint32_t) hexval( b );
+
+ *c |= b << (k*4);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi32_8( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint32_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr >= '0' && *ptr <= '7' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i >= 11 )
+ {
+ b = *(ptr - 10);
+ b -= '0';
+
+ if( b > 3 || i > 11 )
+ {
+ __STO; /* Overflow Flag */
+ }
+ i = 11;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint32_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k*3);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi32_2( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ __mpu_uint32_t b;
+ __mpu_char8_t *ptr;
+ signed int i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr == '0' || *ptr == '1' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ *c = 0; /* result */
+
+ __CLO; /* Overflow Flag */
+ if( i > BITS_PER_FOUR_BYTES )
+ {
+ __STO; /* Overflow Flag */
+ i = BITS_PER_FOUR_BYTES;
+ }
+
+ while( i > 0 )
+ {
+ b = (__mpu_uint32_t) *ptr;
+ b -= '0';
+
+ *c |= b << (k);
+
+ --i; --ptr; ++k;
+
+ } /* End while( i > 0 ) */
+
+ /* Set flags */
+ if( __MPARITY(*c) ) __STP; /* set parity flag */
+ else __CLP;
+
+ if( *c ) __CLZ;
+ else __STZ;
+
+ if( *c & 0x80000000 ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+/* от -2 147 483 648 до +2 147 483 647 */
+void iatoi_32( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ signed int sign = 0, save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' )
+ {
+ if( *ptr == '-' ) sign = 1;
+ ++ptr;
+ }
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoi_32" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi32_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi32_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi32_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi32_10( c, ptr );
+ if( __MFLAG(OF) ) return;
+
+ if( sign ) ineg_32( c, c );
+ if( sign == __MFLAG(SF) ) __CLO;
+ else __STO;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ return;
+ }
+}
+
+
+/* от 0 до +4 294 967 295 */
+void iatoui_32( __mpu_uint32_t *c, __mpu_char8_t *str )
+{
+ signed int save_RF;
+ __mpu_char8_t *ptr;
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' ) ++ptr;
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoui_32" );
+
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi32_2( c, ptr );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi32_16( c, ptr );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ *c = 0;
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ; __CLP; /* __MPARITY(0) == 0 */
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi32_8( c, ptr );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi32_10( c, ptr );
+ return;
+ }
+}
+
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static void satoi_np_10( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT b, *z, *weight=0, *tmp=0, *mul=0;
+ __mpu_char8_t *ptr;
+ signed int save_RF, zero = 1;
+ signed int n, i = 0; /* number of digits */
+
+ errno = 0;
+
+ __CLV;
+
+ /* Allocate memory and *weight = 10; ************************/
+ weight = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !weight )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)weight, 0, np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(weight+np-1) = (EMUSHORT) 10;
+#else
+ *weight = (EMUSHORT) 10;
+#endif
+ /************************************************************/
+
+ /* Allocate memory and *mul = 1; ****************************/
+ mul = (EMUSHORT *)__mpu_sbrk( (int)(2*np*SIZE_OF_EMUSHORT) );
+ if( !mul )
+ {
+ /* fatal error */
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)mul, 0, 2*np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(mul+2*np-1) = (EMUSHORT) 1;
+#else
+ *mul = (EMUSHORT) 1;
+#endif
+ /************************************************************/
+
+ /* Allocate memory and *tmp = 0; ****************************/
+ tmp = (EMUSHORT *)__mpu_sbrk( (int)(2*np*SIZE_OF_EMUSHORT) );
+ if( !tmp )
+ {
+ /* fatal error */
+ /* FREE mul *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)tmp, 0, 2*np*SIZE_OF_EMUSHORT );
+ /************************************************************/
+
+
+ save_RF = __MFLAG(RF); /* save RF */
+
+ ptr = str;
+
+ while( _IS_DIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ z = c + np - 1;
+ n = np;
+ while( n > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --n;
+ }
+ ++z; /* z = c; (result) */
+
+ while( i > 0 )
+ {
+ b = (EMUSHORT) *ptr;
+ b -= '0';
+
+ /* static: sCPY_s2l_emushort2emushort */
+ scpy_s2l_np( (EMUSHORT *)tmp, &b, np*2, 1 );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ imul_np( tmp, tmp+np, mul+np, np*2, np );
+#else
+ imul_np( tmp, tmp, mul, np*2, np );
+#endif
+ if( !__MFLAG(RF) ) /* high part of tmp[] is null */
+ {
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ iadd_np( z, z, tmp+np, np );
+#else
+ iadd_np( z, z, tmp, np );
+#endif
+
+ if( __MFLAG(CF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ /* other flags is correct after ADD */
+
+ /* FREE tmp *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE mul *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ return;
+ }
+
+ }
+ else
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ /* FREE tmp *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE mul *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ return;
+ }
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ imul_np( mul, mul+np, weight, np*2, np );
+#else
+ imul_np( mul, mul, weight, np*2, np );
+#endif
+
+ --i;
+ --ptr;
+
+ if( i && __MFLAG(RF) )
+ {
+ /* overflow */
+ __STO; /* Overflow Flag */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ /* FREE tmp *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE mul *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ return;
+ }
+
+ } /* End while( i ) */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+ __CLO; /* Overflow Flag */
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ /* FREE tmp *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE mul *****************/
+ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+}
+
+static void satoi_np_16( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT b, *z;
+ __mpu_char8_t *ptr;
+ signed int zero = 1;
+ signed int n, i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( _IS_XDIGIT_(*ptr) ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ z = c + np - 1;
+ n = np;
+ while( n > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --n;
+ }
+ ++z; /* z = c; (result) */
+
+ __CLO; /* Overflow Flag */
+ if( i > BITS_PER_EMUSHORT*np/4 )
+ {
+ __STO; /* Overflow Flag */
+ i = BITS_PER_EMUSHORT*np/4;
+ }
+
+ while( i > 0 )
+ {
+ b = (EMUSHORT) *ptr;
+ b = (EMUSHORT) hexval( b );
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[(np-1) - N_PARTS(k*4)] |= b << (N_BITS(k*4));
+#else
+ z[N_PARTS(k*4)] |= b << (N_BITS(k*4));
+#endif
+
+ --i; --ptr; ++k;
+
+ } /* End while( i ) */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi_np_8( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT b, *z;
+ __mpu_char8_t *ptr;
+ signed int zero = 1;
+ signed int n, i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr >= '0' && *ptr <= '7' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ z = c + np - 1;
+ n = np;
+ while( n > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --n;
+ }
+ ++z; /* z = c; (result) */
+
+ __CLO; /* Overflow Flag */
+ if( i >= BITS_PER_EMUSHORT*np/3+1 )
+ {
+ b = (EMUSHORT) *(ptr - BITS_PER_EMUSHORT*np/3);
+ b -= '0';
+
+ if( b > ((BITS_PER_EMUSHORT*np%3) | 1) ||
+ /**********************************************
+ Т.к. число бит всегда четное (кроме того мы
+ ориентируемся только на числа с четным
+ количеством частей [и это очень важно]),
+ остаток от деления его на 3 может быть равен
+ 1 или 2, по этому мы определяем максимальное
+ старшее восьмеричное число как
+ ((BITS_PER_EMUSHORT*np%3) | 1)
+
+ Для двоичного представления это выглядит
+ следующим образом:
+
+ количество бит: 0b0001 (1) 0b0010 (2)
+ операция ИЛИ: |
+ 0b0001 (1) 0b0001 (1)
+ = -----------------------
+ результат: 0b0001 (1) 0b0011 (3)
+
+ ***********************************************/
+ i > (BITS_PER_EMUSHORT*np/3 + 1) )
+ {
+ __STO; /* Overflow Flag */
+ }
+ i = BITS_PER_EMUSHORT*np/3+1;
+ }
+
+ while( i > 0 )
+ {
+ b = (EMUSHORT) *ptr;
+ b -= '0';
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[(np-1) - N_PARTS(k*3)] |= b << (N_BITS(k*3));
+#else
+ z[N_PARTS(k*3)] |= b << (N_BITS(k*3));
+#endif
+
+ /* code for octal only ***********************************/
+ if( k ) /* не делать стыковки при k == 0 */
+ {
+ if( !(k%(BITS_PER_EMUSHORT*(N_PARTS(k*3)+1)/3)) )
+ {/***********************************
+ Если остаток от деления равен 0,
+ то мы работаем на стыке частей
+ (размером BITS_PER_EMUSHORT)
+ целого.
+ ***********************************/
+
+ if( !(N_PARTS(k*3) == np - 1) )
+ {/***********************************
+ Если мы не в старшей части
+ (размером BITS_PER_EMUSHORT)
+ целого.
+ ***********************************/
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[(np-1) - N_PARTS(k*3)-1] |=
+ b >> ((BITS_PER_EMUSHORT*(N_PARTS(k*3)+1))%3);
+#else
+ z[N_PARTS(k*3)+1] |=
+ b >> ((BITS_PER_EMUSHORT*(N_PARTS(k*3)+1))%3);
+#endif
+ }
+ }
+ } /* End if( k ) */
+ /*********************************************************
+
+ Все эти действия легко понять, если проследить их на
+ примере целого, состоящего из четырех частей по 32 бита:
+
+ [part1] 11 111 111 111 111 111 111 111 111 111 111
+ == макс. число в старшем разряде равно
+ (2 | 1) = 3
+
+ [part1] 111 111 111 111 111 111 111 111 111 111 11
+ = сдвиг b для z+1 происходит на 0 бит
+
+ [part1] 1 111 111 111 111 111 111 111 111 111 111 1
+ = сдвиг b для z+1 происходит на 1 бита
+
+ [part0] 11 111 111 111 111 111 111 111 111 111 111
+ == сдвиг b для z+1 происходит на 2 бита
+
+ *********************************************************/
+
+ /* End code for octal only *******************************/
+
+ --i; --ptr; ++k;
+
+ } /* End while( i ) */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+
+static void satoi_np_2( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT b, *z;
+ __mpu_char8_t *ptr;
+ signed int zero = 1;
+ signed int n, i = 0; /* number of digits */
+ signed int k = 0; /* number of shifts */
+
+ __CLV;
+
+ ptr = str;
+
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+
+ while( *ptr == '0' || *ptr == '1' ) { ++ptr; ++i; }
+ --ptr; /* указывает на младшую цифру */
+
+ z = c + np - 1;
+ n = np;
+ while( n > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --n;
+ }
+ ++z; /* z = c; (result) */
+
+ __CLO; /* Overflow Flag */
+ if( i > BITS_PER_EMUSHORT*np )
+ {
+ __STO; /* Overflow Flag */
+ i = BITS_PER_EMUSHORT*np;
+ }
+
+ while( i > 0 )
+ {
+ b = (EMUSHORT) *ptr;
+ b -= '0';
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z[(np-1) - N_PARTS(k)] |= b << (N_BITS(k));
+#else
+ z[N_PARTS(k)] |= b << (N_BITS(k));
+#endif
+
+ --i; --ptr; ++k;
+
+ } /* End while( i ) */
+
+ /* Set flags */
+ /* z = c; (result) */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ z = z + np - 1; /* z = (low part of)c; (result) */
+#endif
+
+ n = np;
+ while( n > 0 )
+ {
+ if( *z ) zero &= 0;
+ else zero &= 1;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ --z;
+#else
+ ++z;
+#endif
+ --n;
+ }
+ if( zero ) __STZ;
+ else __CLZ;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ ++z;
+#else
+ --z;
+#endif
+ if( *z & MASK_SIGN ) __STS;
+ else __CLS;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+void iatoi_np( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT *z;
+ signed int sign = 0, save_RF;
+ __mpu_char8_t *ptr;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iatoi_np (emushort)" );
+ return;
+ }
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' )
+ {
+ if( *ptr == '-' ) sign = 1;
+ ++ptr;
+ }
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoi_np (emushort)" );
+
+ z = c + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --i;
+ }
+ /* ++z; */ /* z = c; (result) */
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi_np_2( c, ptr, np );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi_np_16( c, ptr, np );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ z = c + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --i;
+ }
+ /* ++z; */ /* z = c; (result) */
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi_np_8( c, ptr, np );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi_np_10( c, ptr, np );
+ if( __MFLAG(OF) ) return;
+
+ if( sign ) ineg_np( c, c, np );
+ if( sign == __MFLAG(SF) ) __CLO;
+ else __STO;
+
+ __CLA; /* Auxiliary Carry Flag */
+ __CLC; /* Carry Flag */
+
+ return;
+ }
+}
+
+void iatoui_np( EMUSHORT *c, __mpu_char8_t *str, int np )
+{
+ EMUSHORT *z;
+ __mpu_char8_t *ptr;
+ signed int save_RF;
+ signed int i;
+
+ if( np < 1 || np > NP_MAX )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iatoui_np (emushort)" );
+ return;
+ }
+
+ __CLV;
+
+ save_RF = __MFLAG(RF);
+
+ ptr = str;
+
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+ if( *ptr == '-' || *ptr == '+' ) ++ptr;
+ while( _IS_SPACE_(*ptr) ) ++ptr;
+
+ if( !_IS_DIGIT_( *ptr ) )
+ {
+ /* error: invalid number in string */
+ __integer_invalid_number( (__mpu_char8_t *)"iatoui_np (emushort)" );
+
+ z = c + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --i;
+ }
+ /* ++z; */ /* z = c; (result) */
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ if( save_RF ) __STR;
+ else __CLR;
+
+ return;
+ }
+
+ if( *ptr == '0' )
+ {
+ ++ptr;
+ switch( *ptr )
+ {
+ case 'b':
+ case 'B':
+ ++ptr;
+ /* binary */
+ satoi_np_2( c, ptr, np );
+ return;
+ break;
+
+ case 'x':
+ case 'X':
+ ++ptr;
+ /* hexadecimal */
+ satoi_np_16( c, ptr, np );
+ return;
+ break;
+
+ default:
+ /* octal */
+ if( !_IS_DIGIT_(*ptr) )
+ {
+ z = c + np - 1;
+ i = np;
+ while( i > 0 )
+ {
+ *z = 0; /* bzero Result */
+ --z; --i;
+ }
+ /* ++z; */ /* z = c; (result) */
+
+ /* Set flags */
+ __CLEAR_IFLAGS;
+ __STZ;
+
+ if( save_RF ) __STR;
+ else __CLR;
+ }
+ else
+ {
+ satoi_np_8( c, ptr, np );
+ }
+ return;
+ break;
+
+ } /* End of switch( *ptr ) */
+ }
+ else
+ {
+ satoi_np_10( c, ptr, np );
+ return;
+ }
+}
+
+
+/***************************************************************
+ Операции преобразования целых чисел в символьные строки.
+ Не изменяет флаги: CF, AF, PF, ZF, SF, OF, RF.
+ ***************************************************************/
+/* radix = 2(bin), 8(oct), 10(dec), or 16(hex). */
+/* uf = 0(lowercase letter) or
+ 1(uppercase letter) in prefix and hex-digits. */
+/* sign = 0(' '), or 1('-'). */
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static int hexdigit( int c, int uf )
+{
+ if( c >= 0 && c <= 9 ) return( '0' + c );
+ if( c >= 10 && c <= 15 )
+ {
+ if( uf ) return( 'A' + c - 10 );
+ else return( 'a' + c - 10 );
+ }
+ return( -1 );
+}
+
+/******************
+ str - result
+ a - operand
+ sign - sign
+ */
+static void sitoa8_10( __mpu_char8_t *str, __mpu_uint8_t *a, int sign )
+{
+ __mpu_uint8_t b, x, weight = 10;
+ __mpu_char8_t *s = 0, *ptr;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_BYTE+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_BYTE + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ }
+ else
+ {
+ do
+ {
+ idiv_8( &b, &x, &b, &weight );
+
+ *ptr = 0x30 | x;
+ --ptr;
+
+ } while( b );
+ *ptr = '0'; /* last symbol is zero ('0') */
+
+ if( sign ) *ptr = '-';
+ else ++ptr; /* *ptr is first (not zero) symbol */
+
+ } /* End if( b == 0 ); */
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+/******************
+ str - result
+ a - operand
+ uf - uppercase letter flag
+ */
+static void sitoa8_16( __mpu_char8_t *str, __mpu_uint8_t *a, int uf )
+{
+ __mpu_uint8_t b, x, mask = 15;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_BYTE+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_BYTE + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0'; --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_BYTE / 4 )
+ {
+ x = (b >> (i*4)) & mask;
+ x = (__mpu_uint8_t)hexdigit( x, uf );
+
+ *ptr = x;
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'X';
+ else *ptr = 'x';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+/******************
+ str - result
+ a - operand
+ */
+static void sitoa8_8( __mpu_char8_t *str, __mpu_uint8_t *a )
+{
+ __mpu_uint8_t b, x, mask = 7;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_BYTE+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_BYTE + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_BYTE / 3 + 1 )
+ {
+ x = (b >> (i*3)) & mask;
+
+ *ptr = 0x30 | x;
+ --ptr;
+ ++i;
+ }
+
+ } /* End if( b == 0 ); */
+
+ *ptr = '0';
+
+ while( *ptr == '0' ) ++ptr;
+ --ptr; /* skip zero (exclude first) */
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+/******************
+ str - result
+ a - operand
+ uf - uppercase letter flag
+ */
+static void sitoa8_2( __mpu_char8_t *str, __mpu_uint8_t *a, int uf )
+{
+ __mpu_uint8_t b, x, mask = 1;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_BYTE+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_BYTE + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_BYTE )
+ {
+ x = (b >> (i)) & mask;
+
+ if( x ) *ptr = '1';
+ else *ptr = '0';
+
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'B';
+ else *ptr = 'b';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+/********************************
+ str - result
+ a - operand
+ radix - bin, oct, dec, hex
+ uf - uppercase letter flag
+ */
+void iitoa_8( __mpu_char8_t *str, __mpu_uint8_t *a, int radix, int uf )
+{
+ __mpu_uint8_t b;
+ int sign = 0;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ switch( radix )
+ {
+ case 2:
+ sitoa8_2( str, a, uf );
+ break;
+
+ case 8:
+ sitoa8_8( str, a );
+ break;
+
+ case 10:
+ {
+ b = *a;
+
+ if( b & 0x80 )
+ {
+ sign = 1;
+ ineg_8( &b, &b );
+ }
+ sitoa8_10( str, &b, sign );
+ break;
+ }
+
+ case 16:
+ sitoa8_16( str, a, uf );
+ break;
+
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iitoa_8" );
+
+ *str = NUL;
+ break;
+
+ } /* End of switch( radix ) */
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+void iuitoa_8( __mpu_char8_t *str, __mpu_uint8_t *a, int radix, int uf )
+{
+ switch( radix )
+ {
+ case 2:
+ sitoa8_2( str, a, uf );
+ break;
+ case 8:
+ sitoa8_8( str, a );
+ break;
+ case 10:
+ sitoa8_10( str, a, 0 );
+ break;
+ case 16:
+ sitoa8_16( str, a, uf );
+ break;
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iuitoa_8" );
+
+ *str = NUL;
+ break;
+ } /* End of switch( radix ) */
+}
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+/******************
+ str - result
+ a - operand
+ sign - sign
+ */
+static void sitoa16_10( __mpu_char8_t *str, __mpu_uint16_t *a, int sign )
+{
+ __mpu_uint16_t b, x, weight = 10;
+ __mpu_char8_t *s = 0, *ptr;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_TWO_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_TWO_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ }
+ else
+ {
+ do
+ {
+ idiv_16( &b, &x, &b, &weight );
+
+ *ptr = 0x30 | (__mpu_uint8_t)x;
+ --ptr;
+
+ } while( b );
+ *ptr = '0'; /* last symbol is zero ('0') */
+
+ if( sign ) *ptr = '-';
+ else ++ptr; /* *ptr is first (not zero) symbol */
+
+ } /* End if( b == 0 ) */
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+/******************
+ str - result
+ a - operand
+ uf - uppercase letter flag
+ */
+static void sitoa16_16( __mpu_char8_t *str, __mpu_uint16_t *a, int uf )
+{
+ __mpu_uint16_t b, x, mask = 15;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_TWO_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_TWO_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_TWO_BYTES / 4 )
+ {
+ x = (b >> (i*4)) & mask;
+ x = (__mpu_uint16_t)hexdigit( x, uf );
+
+ *ptr = (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'X';
+ else *ptr = 'x';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+/******************
+ str - result
+ a - operand
+ */
+static void sitoa16_8( __mpu_char8_t *str, __mpu_uint16_t *a )
+{
+ __mpu_uint16_t b, x, mask = 7;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_TWO_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_TWO_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_TWO_BYTES / 3 + 1 )
+ {
+ x = (b >> (i*3)) & mask;
+
+ *ptr = 0x30 | (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+
+ } /* End if( b == 0 ); */
+
+ *ptr = '0';
+
+ while( *ptr == '0' ) ++ptr;
+ --ptr; /* skip zero (exclude first) */
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+/******************
+ str - result
+ a - operand
+ uf - uppercase letter flag
+ */
+static void sitoa16_2( __mpu_char8_t *str, __mpu_uint16_t *a, int uf )
+{
+ __mpu_uint16_t b, x, mask = 1;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_TWO_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_TWO_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0'; --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_TWO_BYTES )
+ {
+ x = (b >> (i)) & mask;
+
+ if( x ) *ptr = '1';
+ else *ptr = '0';
+
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'B';
+ else *ptr = 'b';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+void iitoa_16( __mpu_char8_t *str, __mpu_uint16_t *a, int radix, int uf )
+{
+ __mpu_uint16_t b;
+ int sign = 0;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ switch( radix )
+ {
+ case 2:
+ sitoa16_2( str, a, uf );
+ break;
+
+ case 8:
+ sitoa16_8( str, a );
+ break;
+
+ case 10:
+ {
+ b = *a;
+
+ if( b & 0x8000 )
+ {
+ sign = 1;
+ ineg_16( &b, &b );
+ }
+ sitoa16_10( str, &b, sign );
+ break;
+ }
+
+ case 16:
+ sitoa16_16( str, a, uf );
+ break;
+
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iitoa_16" );
+
+ *str = NUL;
+ break;
+ } /* End of switch( radix ) */
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+void iuitoa_16( __mpu_char8_t *str, __mpu_uint16_t *a, int radix, int uf )
+{
+ switch( radix )
+ {
+ case 2:
+ sitoa16_2( str, a, uf );
+ break;
+ case 8:
+ sitoa16_8( str, a );
+ break;
+ case 10:
+ sitoa16_10( str, a, 0 );
+ break;
+ case 16:
+ sitoa16_16( str, a, uf );
+ break;
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iuitoa_16" );
+
+ *str = NUL;
+ break;
+ } /* End of switch( radix ) */
+}
+
+
+#if BITS_PER_EMUSHORT > 32
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static void sitoa32_10( __mpu_char8_t *str, __mpu_uint32_t *a, int sign )
+{
+ __mpu_uint32_t b, x, weight = 10;
+ __mpu_char8_t *s = 0, *ptr;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_FOUR_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_FOUR_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ }
+ else
+ {
+ do
+ {
+ idiv_32( &b, &x, &b, &weight );
+
+ *ptr = 0x30 | (__mpu_uint8_t)x;
+ --ptr;
+
+ } while( b );
+ *ptr = '0'; /* last symbol is zero ('0') */
+
+ if( sign ) *ptr = '-';
+ else ++ptr; /* *ptr is first (not zero) symbol */
+
+ } /* End if( b == 0 ) */
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+static void sitoa32_16( __mpu_char8_t *str, __mpu_uint32_t *a, int uf )
+{
+ __mpu_uint32_t b, x, mask = 15;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_FOUR_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_FOUR_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_FOUR_BYTES / 4 )
+ {
+ x = (b >> (i*4)) & mask;
+ x = (__mpu_uint32_t)hexdigit( x, uf );
+
+ *ptr = (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'X';
+ else *ptr = 'x';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+static void sitoa32_8( __mpu_char8_t *str, __mpu_uint32_t *a )
+{
+ __mpu_uint32_t b, x, mask = 7;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_FOUR_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_FOUR_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_FOUR_BYTES / 3 + 1 )
+ {
+ x = (b >> (i*3)) & mask;
+
+ *ptr = 0x30 | (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+
+ } /* End if( b == 0 ); */
+
+ *ptr = '0';
+
+ while( *ptr == '0' ) ++ptr;
+ --ptr; /* skip zero (кроме first) */
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+
+static void sitoa32_2( __mpu_char8_t *str, __mpu_uint32_t *a, int uf )
+{
+ __mpu_uint32_t b, x, mask = 1;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+
+ int size = (int)((BITS_PER_FOUR_BYTES+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_FOUR_BYTES + 1;
+
+ b = *a;
+
+ if( b == 0 )
+ {
+ *ptr = '0'; --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_FOUR_BYTES )
+ {
+ x = (b >> (i)) & mask;
+
+ if( x ) *ptr = '1';
+ else *ptr = '0';
+
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'B';
+ else *ptr = 'b';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *************/
+ if( s )
+ __mpu_sbrk( -size );
+ /********************/
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+void iitoa_32( __mpu_char8_t *str, __mpu_uint32_t *a, int radix, int uf )
+{
+ __mpu_uint32_t b;
+ int sign = 0;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ switch( radix )
+ {
+ case 2:
+ sitoa32_2( str, a, uf );
+ break;
+
+ case 8:
+ sitoa32_8( str, a );
+ break;
+
+ case 10:
+ {
+ b = *a;
+
+ if( b & 0x80000000 )
+ {
+ sign = 1;
+ ineg_32( &b, &b );
+ }
+ sitoa32_10( str, &b, sign );
+ break;
+ }
+
+ case 16:
+ sitoa32_16( str, a, uf );
+ break;
+
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iitoa_32" );
+
+ *str = NUL;
+ break;
+
+ } /* End of switch( radix ) */
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+void iuitoa_32( __mpu_char8_t *str, __mpu_uint32_t *a, int radix, int uf )
+{
+ switch( radix )
+ {
+ case 2:
+ sitoa32_2( str, a, uf );
+ break;
+ case 8:
+ sitoa32_8( str, a );
+ break;
+ case 10:
+ sitoa32_10( str, a, 0 );
+ break;
+ case 16:
+ sitoa32_16( str, a, uf );
+ break;
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iuitoa_32" );
+
+ *str = NUL;
+ break;
+ } /* End of switch( radix ) */
+}
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+/***************************************************************
+ STATIC:
+ ***************************************************************/
+static void sitoa_np_10( __mpu_char8_t *str, EMUSHORT *a, int sign, int np )
+{
+ EMUSHORT *b = 0, *x = 0, *weight = 0;
+ __mpu_char8_t *s = 0, *ptr;
+ __mpu_uint8_t y;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_EMUSHORT*np+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ errno = 0;
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ /* Allocate memory and *weight = 10; ************************/
+ weight = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !weight )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)weight, 0, np*SIZE_OF_EMUSHORT );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(weight + np - 1) = (EMUSHORT)10;
+#else
+ *weight = (EMUSHORT)10;
+#endif
+ /************************************************************/
+
+ /* Allocate memory and *x = 0; ******************************/
+ x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !x )
+ {
+ /* fatal error */
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void*)x, 0, np*SIZE_OF_EMUSHORT );
+ /* *x = (EMUSHORT) 0; */
+ /************************************************************/
+
+ /* Allocate memory and *b = 0; ******************************/
+ b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !b )
+ {
+ /* fatal error */
+ /* FREE x *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)b, 0, np*SIZE_OF_EMUSHORT );
+ /* *b = (EMUSHORT) 0; */
+ /************************************************************/
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE x *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_EMUSHORT*np + 1;
+
+ scpy_s2s_np( b, a, np );
+
+ icmp_np( b, x, np ); /* x == 0 */
+ if( __MFLAG(ZF) )
+ {
+ *ptr = '0';
+ }
+ else
+ {
+ do
+ {
+ idiv_np( b, x, b, weight, np );
+
+ icpy_l2s_np_to8( &y, x, np );
+
+ *ptr = 0x30 | y;
+ --ptr;
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(weight + np - 1) = (EMUSHORT)0;
+#else
+ *weight = (EMUSHORT)0;
+#endif
+ icmp_np( b, weight, np ); /* CMP b,0 */
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ *(weight + np - 1) = (EMUSHORT)10;
+#else
+ *weight = (EMUSHORT)10;
+#endif
+
+ } while( !__MFLAG(ZF) );
+ *ptr = '0'; /* last symbol is zero ('0') */
+
+ if( sign ) *ptr = '-';
+ else ++ptr; /* *ptr is first (not zero) symbol */
+
+ } /* End if( b == 0 ) */
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *********************/
+ if( s ) __mpu_sbrk( -size );
+ /****************************/
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE x *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ /* FREE weight **************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+static void sitoa_np_16( __mpu_char8_t *str, EMUSHORT *a, int uf, int np )
+{
+ EMUSHORT *b = 0, x, mask = 15;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_EMUSHORT*np+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ errno = 0;
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ /* Allocate memory and *b = 0; ******************************/
+ b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !b )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)b, 0, np*SIZE_OF_EMUSHORT );
+ /* *b = (EMUSHORT)0; */
+ /************************************************************/
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_EMUSHORT*np + 1;
+
+ icmp_np( a, b, np ); /* b = 0 */
+ if( __MFLAG(ZF) )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_EMUSHORT*np / 4 )
+ {
+ ishrn_np( b, a, (i*4), np );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = *(b+np-1) & mask;
+#else
+ x = *b & mask;
+#endif
+ x = (EMUSHORT)hexdigit( x, uf );
+
+ *ptr = (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'X';
+ else *ptr = 'x';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *********************/
+ if( s ) __mpu_sbrk( -size );
+ /****************************/
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+static void sitoa_np_8( __mpu_char8_t *str, EMUSHORT *a, int np )
+{
+ EMUSHORT *b = 0, x, mask = 7;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_EMUSHORT*np+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ errno = 0;
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ /* Allocate memory and *b = 0; ******************************/
+ b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !b )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)b, 0, np*SIZE_OF_EMUSHORT );
+ /* *b = (EMUSHORT)0; */
+ /************************************************************/
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_EMUSHORT*np + 1;
+
+ icmp_np( a, b, np ); /* b = 0 */
+ if( __MFLAG(ZF) )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_EMUSHORT*np / 3 + 1 )
+ {
+ ishrn_np( b, a, (i*3), np );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = *(b+np-1) & mask;
+#else
+ x = *b & mask;
+#endif
+
+ *ptr = 0x30 | (__mpu_uint8_t)x;
+ --ptr;
+ ++i;
+ }
+
+ } /* End if( b == 0 ); */
+
+ *ptr = '0';
+
+ while( *ptr == '0' ) ++ptr;
+ --ptr; /* skip zero (кроме first) */
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *********************/
+ if( s ) __mpu_sbrk( -size );
+ /****************************/
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+static void sitoa_np_2( __mpu_char8_t *str, EMUSHORT *a, int uf, int np )
+{
+ EMUSHORT *b = 0, x, mask = 1;
+ __mpu_char8_t *s = 0, *ptr;
+ int i;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ int size = (int)((BITS_PER_EMUSHORT*np+3)*sizeof( __mpu_char8_t )); /* n_bits + prefix[2] + '\0' */
+
+ errno = 0;
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ /* Allocate memory and *b = 0; ******************************/
+ b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !b )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)b, 0, np*SIZE_OF_EMUSHORT );
+ /* *b = (EMUSHORT)0; */
+ /************************************************************/
+
+ s = (__mpu_char8_t *)__mpu_sbrk( size );
+ if( !s )
+ {
+ /* fatal error */
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+ return;
+ }
+ (void)memset( (void *)s, 0, (size_t)size );
+
+ ptr = s + BITS_PER_EMUSHORT*np + 1;
+
+ icmp_np( a, b, np ); /* b = 0 */
+ if( __MFLAG(ZF) )
+ {
+ *ptr = '0';
+ --ptr;
+ }
+ else
+ {
+ i = 0;
+ while( i < BITS_PER_EMUSHORT*np )
+ {
+ ishrn_np( b, a, (i), np );
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ x = *(b+np-1) & mask;
+#else
+ x = *b & mask;
+#endif
+
+ if( x ) *ptr = '1';
+ else *ptr = '0';
+
+ --ptr;
+ ++i;
+ }
+ ++ptr;
+ while( *ptr == '0' ) ++ptr; /* skip zero */
+ --ptr;
+
+ } /* End if( b == 0 ); */
+
+ if( uf ) *ptr = 'B';
+ else *ptr = 'b';
+ --ptr;
+ *ptr = '0';
+
+ strncpy( (char *)str, (const char *)ptr, (size_t)size );
+
+ /* FREE *********************/
+ if( s ) __mpu_sbrk( -size );
+ /****************************/
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+/*
+ End of STATIC.
+ ***************************************************************/
+
+void iitoa_np( __mpu_char8_t *str, EMUSHORT *a, int radix, int uf, int np )
+{
+ EMUSHORT *b = 0;
+ int sign = 0;
+ __mpu_uint32_t flags; /* temporary saved mpu flags register */
+
+ errno = 0;
+
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iitoa_np" );
+ return;
+ }
+
+ __CLV;
+
+ flags = __MPU_FLAGS; /* Store all Flags */
+
+ /* Allocate memory and *b = 0; ***((*************************/
+ b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
+ if( !b )
+ {
+ /* fatal error */
+ return;
+ }
+ (void)memset( (void *)b, 0, np*SIZE_OF_EMUSHORT );
+ /* *b = (EMUSHORT) 0; */
+ /************************************************************/
+
+ switch( radix )
+ {
+ case 2:
+ sitoa_np_2( str, a, uf, np );
+ break;
+
+ case 8:
+ sitoa_np_8( str, a, np );
+ break;
+
+ case 10:
+ {
+ scpy_s2s_np( b, a, np ); /* b = a; */
+
+#if MPU_WORD_ORDER_BIG_ENDIAN == 1
+ if( *(b) & MASK_SIGN )
+#else
+ if( *(b+np-1) & MASK_SIGN )
+#endif
+ {
+ sign = 1;
+ ineg_np( b, b, np );
+ }
+ sitoa_np_10( str, b, sign, np );
+ break;
+ }
+
+ case 16:
+ sitoa_np_16( str, a, uf, np );
+ break;
+
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iitoa_np" );
+
+ *str = NUL;
+ break;
+
+ } /* End of switch( radix ) */
+
+ /* FREE b *******************/
+ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
+ /****************************/
+
+ __MPU_FLAGS = flags; /* Restore all Flags */
+}
+
+void iuitoa_np( __mpu_char8_t *str, EMUSHORT *a, int radix, int uf, int np )
+{
+ if( np == 0 )
+ {
+ /* error: Invalid size of operand(s) */
+ __integer_invalid_size( (__mpu_char8_t *)"iuitoa_np" );
+ return;
+ }
+
+ __CLV;
+
+ switch( radix )
+ {
+ case 2:
+ sitoa_np_2( str, a, uf, np );
+ break;
+ case 8:
+ sitoa_np_8( str, a, np );
+ break;
+ case 10:
+ sitoa_np_10( str, a, 0, np );
+ break;
+ case 16:
+ sitoa_np_16( str, a, uf, np );
+ break;
+ default:
+ /* error: invalid radix for string */
+ __integer_invalid_radix( (__mpu_char8_t *)"iuitoa_np" );
+
+ *str = NUL;
+ break;
+
+ } /* End of switch( radix ) */
+}
+
+
+/***************************************************************
+ Hide internal symbols:
+ ***************************************************************/
+__mpu_hidden_decl(iadd_8);
+__mpu_hidden_decl(iadc_8);
+__mpu_hidden_decl(isub_8);
+__mpu_hidden_decl(isbb_8);
+
+__mpu_hidden_decl(iadd_16);
+__mpu_hidden_decl(iadc_16);
+__mpu_hidden_decl(isub_16);
+__mpu_hidden_decl(isbb_16);
+
+__mpu_hidden_decl(iadd_32);
+__mpu_hidden_decl(iadc_32);
+__mpu_hidden_decl(isub_32);
+__mpu_hidden_decl(isbb_32);
+
+__mpu_hidden_decl(iadd_np);
+__mpu_hidden_decl(iadc_np);
+__mpu_hidden_decl(isub_np);
+__mpu_hidden_decl(isbb_np);
+
+
+__mpu_hidden_decl(ishl_8);
+__mpu_hidden_decl(ishr_8);
+__mpu_hidden_decl(isal_8);
+__mpu_hidden_decl(isar_8);
+
+__mpu_hidden_decl(ishl_16);
+__mpu_hidden_decl(ishr_16);
+__mpu_hidden_decl(isal_16);
+__mpu_hidden_decl(isar_16);
+
+__mpu_hidden_decl(ishl_32);
+__mpu_hidden_decl(ishr_32);
+__mpu_hidden_decl(isal_32);
+__mpu_hidden_decl(isar_32);
+
+__mpu_hidden_decl(ishl_np);
+__mpu_hidden_decl(ishr_np);
+__mpu_hidden_decl(isal_np);
+__mpu_hidden_decl(isar_np);
+
+
+__mpu_hidden_decl(irol_8);
+__mpu_hidden_decl(iror_8);
+__mpu_hidden_decl(ircl_8);
+__mpu_hidden_decl(ircr_8);
+
+__mpu_hidden_decl(irol_16);
+__mpu_hidden_decl(iror_16);
+__mpu_hidden_decl(ircl_16);
+__mpu_hidden_decl(ircr_16);
+
+__mpu_hidden_decl(irol_32);
+__mpu_hidden_decl(iror_32);
+__mpu_hidden_decl(ircl_32);
+__mpu_hidden_decl(ircr_32);
+
+__mpu_hidden_decl(irol_np);
+__mpu_hidden_decl(iror_np);
+__mpu_hidden_decl(ircl_np);
+__mpu_hidden_decl(ircr_np);
+
+
+__mpu_hidden_decl(ishln_8);
+__mpu_hidden_decl(ishrn_8);
+__mpu_hidden_decl(isaln_8);
+__mpu_hidden_decl(isarn_8);
+
+__mpu_hidden_decl(ishln_16);
+__mpu_hidden_decl(ishrn_16);
+__mpu_hidden_decl(isaln_16);
+__mpu_hidden_decl(isarn_16);
+
+__mpu_hidden_decl(ishln_32);
+__mpu_hidden_decl(ishrn_32);
+__mpu_hidden_decl(isaln_32);
+__mpu_hidden_decl(isarn_32);
+
+__mpu_hidden_decl(ishln_np);
+__mpu_hidden_decl(ishrn_np);
+__mpu_hidden_decl(isaln_np);
+__mpu_hidden_decl(isarn_np);
+
+
+__mpu_hidden_decl(iroln_8);
+__mpu_hidden_decl(irorn_8);
+__mpu_hidden_decl(ircln_8);
+__mpu_hidden_decl(ircrn_8);
+
+__mpu_hidden_decl(iroln_16);
+__mpu_hidden_decl(irorn_16);
+__mpu_hidden_decl(ircln_16);
+__mpu_hidden_decl(ircrn_16);
+
+__mpu_hidden_decl(iroln_32);
+__mpu_hidden_decl(irorn_32);
+__mpu_hidden_decl(ircln_32);
+__mpu_hidden_decl(ircrn_32);
+
+__mpu_hidden_decl(iroln_np);
+__mpu_hidden_decl(irorn_np);
+__mpu_hidden_decl(ircln_np);
+__mpu_hidden_decl(ircrn_np);
+
+
+__mpu_hidden_decl(inot_8);
+__mpu_hidden_decl(inot_16);
+__mpu_hidden_decl(inot_32);
+__mpu_hidden_decl(inot_np);
+
+__mpu_hidden_decl(ineg_8);
+__mpu_hidden_decl(ineg_16);
+__mpu_hidden_decl(ineg_32);
+__mpu_hidden_decl(ineg_np);
+
+__mpu_hidden_decl(iand_8);
+__mpu_hidden_decl(iand_16);
+__mpu_hidden_decl(iand_32);
+__mpu_hidden_decl(iand_np);
+
+__mpu_hidden_decl(itest_8);
+__mpu_hidden_decl(itest_16);
+__mpu_hidden_decl(itest_32);
+__mpu_hidden_decl(itest_np);
+
+__mpu_hidden_decl(icmp_8);
+__mpu_hidden_decl(icmp_16);
+__mpu_hidden_decl(icmp_32);
+__mpu_hidden_decl(icmp_np);
+
+__mpu_hidden_decl(ior_8);
+__mpu_hidden_decl(ior_16);
+__mpu_hidden_decl(ior_32);
+__mpu_hidden_decl(ior_np);
+
+__mpu_hidden_decl(ixor_8);
+__mpu_hidden_decl(ixor_16);
+__mpu_hidden_decl(ixor_32);
+__mpu_hidden_decl(ixor_np);
+
+__mpu_hidden_decl(iinc_8);
+__mpu_hidden_decl(iinc_16);
+__mpu_hidden_decl(iinc_32);
+__mpu_hidden_decl(iinc_np);
+
+__mpu_hidden_decl(idec_8);
+__mpu_hidden_decl(idec_16);
+__mpu_hidden_decl(idec_32);
+__mpu_hidden_decl(idec_np);
+
+__mpu_hidden_decl(icpy_8);
+__mpu_hidden_decl(icpy_16);
+__mpu_hidden_decl(icpy_32);
+
+__mpu_hidden_decl(icpy_s2l_8to16);
+__mpu_hidden_decl(icpy_s2l_8to32);
+__mpu_hidden_decl(icpy_s2l_8to_np);
+
+__mpu_hidden_decl(icpy_s2l_16to32);
+__mpu_hidden_decl(icpy_s2l_16to_np);
+
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(icpy_s2l_32to_np);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(icpy_l2s_16to8);
+__mpu_hidden_decl(icpy_l2s_32to8);
+__mpu_hidden_decl(icpy_l2s_np_to8);
+
+__mpu_hidden_decl(icpy_l2s_32to16);
+__mpu_hidden_decl(icpy_l2s_np_to16);
+
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(icpy_l2s_np_to32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(icpy_np);
+
+
+__mpu_hidden_decl(icvt_s2l_8to16);
+__mpu_hidden_decl(icvt_s2l_8to32);
+__mpu_hidden_decl(icvt_s2l_8to_np);
+
+__mpu_hidden_decl(icvt_s2l_16to32);
+__mpu_hidden_decl(icvt_s2l_16to_np);
+
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(icvt_s2l_32to_np);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(icvt_l2s_16to8);
+__mpu_hidden_decl(icvt_l2s_32to8);
+__mpu_hidden_decl(icvt_l2s_np_to8);
+
+__mpu_hidden_decl(icvt_l2s_32to16);
+__mpu_hidden_decl(icvt_l2s_np_to16);
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(icvt_l2s_np_to32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(icvt_np);
+
+
+__mpu_hidden_decl(ixchg_8);
+__mpu_hidden_decl(ixchg_16);
+__mpu_hidden_decl(ixchg_32);
+__mpu_hidden_decl(ixchg_np);
+
+
+__mpu_hidden_decl(imul_8);
+__mpu_hidden_decl(imul_16);
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(imul_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(ismul_8);
+__mpu_hidden_decl(ismul_16);
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(ismul_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+__mpu_hidden_decl(idiv_8);
+__mpu_hidden_decl(idiv_16);
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(idiv_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(isdiv_8);
+__mpu_hidden_decl(isdiv_16);
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(isdiv_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+
+__mpu_hidden_decl(imul_np);
+__mpu_hidden_decl(ismul_np);
+
+__mpu_hidden_decl(idiv_np);
+__mpu_hidden_decl(isdiv_np);
+
+
+
+__mpu_hidden_decl(iatoi_8);
+__mpu_hidden_decl(iatoui_8);
+
+__mpu_hidden_decl(iatoi_16);
+__mpu_hidden_decl(iatoui_16);
+
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(iatoi_32);
+__mpu_hidden_decl(iatoui_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(iatoi_np);
+__mpu_hidden_decl(iatoui_np);
+
+
+__mpu_hidden_decl(iitoa_8);
+__mpu_hidden_decl(iuitoa_8);
+
+__mpu_hidden_decl(iitoa_16);
+__mpu_hidden_decl(iuitoa_16);
+
+#if BITS_PER_EMUSHORT > 32
+__mpu_hidden_decl(iitoa_32);
+__mpu_hidden_decl(iuitoa_32);
+#endif /* BITS_PER_EMUSHORT > 32 */
+
+__mpu_hidden_decl(iitoa_np);
+__mpu_hidden_decl(iuitoa_np);
+
+
+/*
+ End of hide internal symbols.
+ ***************************************************************/