/*************************************************************** __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 #endif #include /* errno(3) */ #include /* strcpy(3) */ #include /* bzero(3) */ #include #include #include #include #include #include #include #include /*************************************************************** 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 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 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. [фактически ]. Не изменяет значения операндов. Выставляет флаги: 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 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 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. ***************************************************************/