author: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300
committer: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300
commit: 3c780c88a0a0e98f7bb1ceaf7843c4560d2e0ce4
parent: 31f615c1e5a07398bdd68c74b81fbe64c45f169a
Commit Summary:
Diffstat:
12 files changed, 322 insertions, 2 deletions
diff --git a/man/Makefile.am b/man/Makefile.am
index 53688a4..a21d8d2 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -2,7 +2,11 @@
SUBDIRS = ru
MAN3 = iadc.3mpu iadd.3mpu \
- isbb.3mpu isub.3mpu
+ isbb.3mpu isub.3mpu \
+ shifts.3mpu \
+ isal.3mpu isar.3mpu \
+ ishl.3mpu ishr.3mpu
+
MAN7 = libmpu.7
diff --git a/man/isal.3mpu b/man/isal.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/isal.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/isar.3mpu b/man/isar.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/isar.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ishl.3mpu b/man/ishl.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ishl.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ishr.3mpu b/man/ishr.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ishr.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ru/Makefile.am b/man/ru/Makefile.am
index eedea05..f397efa 100644
--- a/man/ru/Makefile.am
+++ b/man/ru/Makefile.am
@@ -4,7 +4,10 @@ LANG = ru
mandir = @mandir@/$(LANG)
MAN3 = iadc.3mpu iadd.3mpu \
- isbb.3mpu isub.3mpu
+ isbb.3mpu isub.3mpu \
+ shifts.3mpu \
+ isal.3mpu isar.3mpu \
+ ishl.3mpu ishr.3mpu
MAN7 = libmpu.7
diff --git a/man/ru/isal.3mpu b/man/ru/isal.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ru/isal.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ru/isar.3mpu b/man/ru/isar.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ru/isar.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ru/ishl.3mpu b/man/ru/ishl.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ru/ishl.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ru/ishr.3mpu b/man/ru/ishr.3mpu
new file mode 100644
index 0000000..1957f71
--- /dev/null
+++ b/man/ru/ishr.3mpu
@@ -0,0 +1 @@
+.so man3/shifts.3mpu
diff --git a/man/ru/shifts.3mpu b/man/ru/shifts.3mpu
new file mode 100644
index 0000000..3252b01
--- /dev/null
+++ b/man/ru/shifts.3mpu
@@ -0,0 +1,165 @@
+.\" Copyright 2024 Andrew V.Kosteltsev (kx@radix-linux.su)
+.\"
+.\"
+.TH shifts 3 "December 27, 2024" "libmpu" "LibMPU Programmer's Manual"
+.SH NAME
+\fBishl\fP, \fBishr\fP, \fBisal\fP, \fBisar\fP \- операции сдвига на один бит
+.SH SYNOPSIS
+.nf
+.B #include <libmpu.h>
+.PP
+.BI "void ishl( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void ishr( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isal( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isar( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.fi
+.SH DESCRIPTION
+Для операций сдвигов на один бит входным операндом служит переменная размером \fBnb\fP байт,
+находящаяся по адресу \fBa\fP, результат помещается в переменную того же размера,
+расположенную по адресу \fBc\fP. Пространства, занимаемые входной и выходной переменной
+в памяти могут пересекаться, как частично, так и полностью, что не влияет на правильность
+получаемого результата. Содержимое переменной, расположенной по адресу \fBa\fP останется
+неизменным, после выполнения операции, если занимаемое ей пространство не пересекается
+с пространством, занимаемым переменной \fBc\fP.
+.PP
+При выполнениии операций сдвига, флаг переноса \fBC\fP всегда содержит значение последнего
+выдвинутого бита. Существуют следующие виды операций сдвига:
+.PP
+
+.RS 3
+ SHL \- логический беззнаковый сдвиг влево на один бит.
+.RE
+.RS 3
+ SHR \- логический беззнаковый сдвиг вправо на один бит.
+.RE
+.RS 3
+ SAL \- арифметический сдвиг влево на один бит.
+.RE
+.RS 3
+ SAR \- арифметический сдвиг вправо на один бит.
+.RE
+
+.PP
+Следующие таблицы иллюстрируют выполнение операций \fBishl\fP, \fBishr\fP.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SHL(<<): │ C │ значение операнда │ заполнение │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ до операции │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ после операции │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SHR(>>): │ заполнение │ значение операнда │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ до операции │ 0 │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ после операции │ │ 01011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+Из таблиц видно, что при любом логическом сдвиге на освободившееся место всегда задвигается 0.
+Флаг переполнения \fBO\fP выставляется, если в результате операции операнд изменил знак.
+.PP
+Операция арифметического сдвига влево \fBisal\fP действует аналогично операции \fBishl\fP
+(также на пустое место справа задвигается 0). Операция арифметического сдвига вправо действует
+иначе: в освобождающуюся позицию слева копируется знаковый бит исходного операнда.
+Действие операций \fBisal\fP и \fBisar\fP показано с помощью следующих таблиц.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SAL(<<): │ C │ значение операнда │ заполнение │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ до операции │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ после операции │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SAR(>>): │ заполнение │ значение операнда │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ до операции │ sign(1) │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ после операции │ │ 11011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+Флаг переполнения при выполнении операции \fBisal\fP выставляется таким же образом, как
+и при операции \fBishl\fP. При выполнении операции \fBisar\fP, операнд не может изменить
+свой знак. Многократный сдвиг \fBisar\fP может, в конце концов, привести к потере значения,
+и положительное число задвинется в 0, а отрицательное в -1. По этому флаг переполнения \fBO\fP
+для операции \fBisar\fP сбрасывается в 0.
+.PP
+При выполнении операций \fBisal\fP, \fBisar\fP, \fBishl\fP, \fBishr\fP, так же выставляются
+флаги четности \fBP\fP, знака \fBS\fP и нуля \fBZ\fP. Флаг переноса из младшей тетрады \fBA\fP
+не определяется и просто сбрасывается в 0.
+.PP
+Сдвиг влево можно применять для удваивания чисел, а сдвиг вправо \- для деления на 2. Эти операции
+выполняются значительно быстрее, чем операции умножения и деления. Деление пополам нечетных чисел
+(например, 5 или 7) образует меньшие значения (2 или 3, соответственно) и устанавливает флаг
+переноса \fBC\fP в 1. При этом \fBC\fP, фактически, содержит остаток от деления. Такое использование
+операций сдвига требует контроля за флагом переполнения \fBO\fP. Для простоты, рассмотрим контроль
+флагов на 4\-битных знаковых переменных:
+.SS Примеры с 4\-битными операндами:
+\fBУмножение на 2\fP:
+.nf
+SAL(0111) = 7; результат = 1110 = -2, ошибка, должно быть 14, CF = 0, OF = 1
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SHR(1000) = -8; результат = 0100 = 4, ошибка, должно быть -4, CF = 0, OF = 1
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SAR(1000) = -8; результат = 1100 = -4, абсолютно точно, CF = 0, OF = 0
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SAR(0111) = 7; результат = 0011 = 3, остаток 1 (см. флаг C), абсолютно точно, CF = 1, OF = 0
+.fi
+.sp
+.SH EXAMPLES
+.nf
+.sp
+#include <libmpu.h>
+#include <stdio.h>
+
+int main( void )
+{
+ int rc = 0;
+
+ __mpu_init();
+ __mpu_extra_warnings = 1;
+
+ {
+ mpu_int128_t c, a;
+ int nb = NB_I8;
+ __mpu_char8_t sc[32], sa[32];
+
+ iatoi( a, "0b10110111", nb ); /* evaluate the A variable */
+
+ ishl( c, a, nb );
+ iitoa( sa, a, RADIX_BIN, LOWERCASE, nb ); /* convert A value to ASCII string SA */
+ iitoa( sc, c, RADIX_BIN, LOWERCASE, nb ); /* convert C value to ASCII string SC */
+ printf( "a = %s;\n", sa ); /* c = 0b10110111; */
+ printf( "c = %s;\n", sc ); /* c = 0b01101110; */
+ printf( "carry = %d;\n", __mpu_gtc() ); /* Carry Flag */
+ printf( "overflow = %d;\n", __mpu_gto() ); /* Overflow Flag */
+ }
+
+ __mpu_free_context();
+
+ return( rc );
+}
+.fi
+.SH SEE ALSO
+.BR iadd(3),
+.BR iadc(3),
+.BR isub(3),
+.BR isbb(3).
+
diff --git a/man/shifts.3mpu b/man/shifts.3mpu
new file mode 100644
index 0000000..00743c9
--- /dev/null
+++ b/man/shifts.3mpu
@@ -0,0 +1,163 @@
+.\" Copyright 2024 Andrew V.Kosteltsev (kx@radix-linux.su)
+.\"
+.\"
+.TH shifts 3 "December 27, 2024" "libmpu" "LibMPU Programmer's Manual"
+.SH NAME
+\fBishl\fP, \fBishr\fP, \fBisal\fP, \fBisar\fP \- one\-bit shifts
+.SH SYNOPSIS
+.nf
+.B #include <libmpu.h>
+.PP
+.BI "void ishl( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void ishr( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isal( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isar( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.fi
+.SH DESCRIPTION
+For one\-bit shift operations, the input operand is a variable of size \fBnb\fP bytes located
+at address \fBa\fP, the result is placed in a variable of the same size located at address \fBc\fP.
+The spaces occupied by the input and output variable in memory may overlap, either partially or
+completely, which does not affect the correctness of the result obtained. The content of the
+variable located at address \fBa\fP will remain unchanged after the operation if the space
+occupied by it does not overlap with the space occupied by variable \fBc\fP.
+.PP
+When performing shift operations, the carry flag \fBC\fP always contains the value of the last
+putted forward bit. There are the following types of shift operations:
+.PP
+
+.RS 3
+ SHL \- logical unsigned shift to the left by one bit.
+.RE
+.RS 3
+ SHR \- logical unsigned shift to the right by one bit.
+.RE
+.RS 3
+ SAL \- arithmetic shift to the left by one bit.
+.RE
+.RS 3
+ SAR \- arithmetic shift to the right by one bit.
+.RE
+
+.PP
+The following tables illustrate the execution of the operations \fBishl\fP, \fBishr\fP.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SHL(<<): │ C │ operand value │ filling │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ before │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ after │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SHR(>>): │ filling │ operand value │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ before │ 0 │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ after │ │ 01011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+The tables show that any logical shift always results in a 0 being pushed into the vacated space.
+The overflow flag \fBO\fP is set if the operand has changed sign as a result of the operation.
+.PP
+The left arithmetic shift operation \fBisal\fP operates in the same way as \fBishl\fP (0 is
+also moved to the empty space on the right). The right arithmetic shift operation works
+differently: the sign bit of the original operand is copied to the empty position on the left.
+The action of the \fBisal\fP and \fBisar\fP operations is shown in the following tables.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SAL(<<): │ C │ operand value │ filling │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ before │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ after │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SAR(>>): │ filling │ operand value │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ before │ sign(1) │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ after │ │ 11011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+The overflow flag for the \fBisal\fP operation is set in the same way as for the \fBishl\fP
+operation. When performing an \fBisar\fP operation, the operand cannot change its sign. Repeated
+shifting of \fBisar\fP may eventually cause a loss of value, and a positive number will be shifted
+to 0 and a negative number to -1. Therefore, the overflow flag \fBO\fP for the \fBisar\fP operation
+is reset to 0.
+.PP
+When performing \fBisal\fP, \fBisar\fP, \fBishl\fP, \fBishr\fP operations, the parity \fBP\fP,
+sign \fBS\fP and zero \fBZ\fP flags are also set. The carry flag from the lowest tetrad \fBA\fP
+is not defined and is simply reset to 0.
+.PP
+Left shift can be used to double numbers, and right shift can be used to divide by 2. These operations
+are much faster than multiplication and division operations. Dividing odd numbers (such as 5 or 7) in
+half forms smaller values (2 or 3, respectively) and sets the carry flag \fBC\fP to 1. In doing so,
+\fBC\fP actually contains the remainder of the division. This use of shift operations requires control
+of the overflow flag \fBO\fP. For simplicity, consider flag control on 4\-bit signed variables:
+.SS Examples with 4\-bit operands:
+\fBMultiplying by 2\fP:
+.nf
+SAL(0111) = 7; result = 1110 = -2, mistake, there must be 14, CF = 0, OF = 1
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SHR(1000) = -8; result = 0100 = 4, mistake, there must be -4, CF = 0, OF = 1
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SAR(1000) = -8; result = 1100 = -4, exactly, CF = 0, OF = 0
+.fi
+.sp
+\fBDividing by 2\fP:
+.nf
+SAR(0111) = 7; result = 0011 = 3, remainder 1 (see carry flag C), exactly, CF = 1, OF = 0
+.fi
+.sp
+.SH EXAMPLES
+.nf
+.sp
+#include <libmpu.h>
+#include <stdio.h>
+
+int main( void )
+{
+ int rc = 0;
+
+ __mpu_init();
+ __mpu_extra_warnings = 1;
+
+ {
+ mpu_int128_t c, a;
+ int nb = NB_I8;
+ __mpu_char8_t sc[32], sa[32];
+
+ iatoi( a, "0b10110111", nb ); /* evaluate the A variable */
+
+ ishl( c, a, nb );
+ iitoa( sa, a, RADIX_BIN, LOWERCASE, nb ); /* convert A value to ASCII string SA */
+ iitoa( sc, c, RADIX_BIN, LOWERCASE, nb ); /* convert C value to ASCII string SC */
+ printf( "a = %s;\n", sa ); /* c = 0b10110111; */
+ printf( "c = %s;\n", sc ); /* c = 0b01101110; */
+ printf( "carry = %d;\n", __mpu_gtc() ); /* Carry Flag */
+ printf( "overflow = %d;\n", __mpu_gto() ); /* Overflow Flag */
+ }
+
+ __mpu_free_context();
+
+ return( rc );
+}
+.fi
+.SH SEE ALSO
+.BR iadd(3),
+.BR iadc(3),
+.BR isub(3),
+.BR isbb(3).
+