- Вопрос по ASHC
-
? Дмитрий - 29.09.2018 00:12
В описании сказано, что:
¤
Содержимое регистра, и регистра с номером, полученным установкой младшего бита в номере указанного регистра, рассмаиривается как одно 32 - битовое слово, причем в регистре с большим номером содержатся младшие биты, а регистре с меньшим - старшие, дигается влево или вправо на число позиций, указанное счетчике сдвига. Счетчиком сдвига являются младшие 6 бит операнда-источника. Отрицательное значение счетчика вызывает сдвиг вправо, положительное - влево. Если номер регистра-приемника нечетный, правый сдвиг становится вращением. 16-разрядное слово вращается вправо на число позиий, указанное в счетчике сдвига. При правом сдвиге распространяется старший бит, при левом сдвиге младший бит грузится нулем. V устанавливается, если при сдвиге изменялся знак операнда, иначе очищается; c загружается последним выдвинутым из 32-битового операнда битом.
¤
Непонятка во фразе "Если номер регистра-приемника нечетный, правый сдвиг становится вращением. 16-разрядное слово вращается вправо на число позиий, указанное в счетчике сдвига." Т.е., емнип, двухрегистровый ASHC превращается в однорегистровый ROR с регулилируемым кол-вом сдвигов. А если регистр нечетный и сдвиг указан влево? Будет ROL или ничего не будет? По идее ROL, но кто его знает - походу описание неполное.
-
? gid - 29.09.2018 09:36
Кто мешает взять и попробовать на БК с эмуляцией инструкций EIS/FIS?
Мне, например, лень мешает. Поэтому я предполагаю такой алгоритм работы команды:
ASHC(rd,n)
{
t_hi = rd;
t_lo = rd | 1;
if (n<0)
{
n = -n;
while(n>0)
{
ASR t_hi;
ROR t_lo;
n--;
}
}
else
{
while(n>0)
{
ASL t_lo;
ROL t_hi;
n--;
}
}
rd = t_hi;
(rd | 1) = t_lo;
}
И по нему выходит, что если регистр-операнд нечётный, то получается не просто PDPшный ROR, ROL. А настоящий циклический сдвиг, почти такой, как на интеловском х86, когда бит С не участвует в сдвиге, а только отображает разряд, вытесненный из регистра.
-
? Дмитрий - 01.10.2018 11:13
>> Мне, например, лень мешает
Лень - двигатель прогресса, но не в этом случае. :) Мне мешает закопанные в кладовке телек (монитор) и БК10. Плюс надо все это где-то собрать, вспомнить на каких дискетах есть дос да модуль арифметический.
¤
Про сдвиг я понял, просто в описании не описан левый сдвиг (даже в официальных handbook'ах), а только правый.
-
? gid - 01.10.2018 12:16
Можно ещё поизучать исходники эмуляции EIS/FIS их два варианта - дизассемблированный из ПЗУ 326 и чуточку другой вариант - исходник прилагался к ассемблеру Турбо8. Но тут мне уже не лень, а тупо некогда. В эмуляции предполагается, что результат соответствует аппаратной реализации, она ж всё равно микрокодом делалась, так что алгоритмы должны быть идентичны, что в микрокоде, что на ассемблере.
Я ведь просто предположил, как оно работает, и как бы сам реализовывал.
А как на самом деле древним разработчикам тараканы в голове нашептали, я не знаю.
Вдруг там приделали жёсткую проверку на нечётность регистра и при этом делают только правый сдвиг отдельной веткой алгоритма, а левый не делают, просто выходят с ошибкой.
-
? Дмитрий - 01.10.2018 13:08
Я уже накидал на асме реализацию ASH - жаль в х86 при занесении данных в регистр не выставляются флаги по результату, пришлось добавлять test для этого. Обошлось без сдвигов на 1 меньше и прочего. Получилось коротко и просто. Щас ASHC сделаю по тому же принципу.
-
? Дмитрий - 01.10.2018 21:10
>> получается не просто PDPшный ROR, ROL. А настоящий циклический сдвиг, почти такой, как на интеловском х86, когда бит С не участвует в сдвиге, а только отображает разряд, вытесненный из регистра.
Покрутил я ASHC. Как раз и выходит, что с нечетным регистром получается как раз ПДПшный ROL/ROR. Интеловский ROL/ROR крутит биты внутри, когда вытесняемый бит попадает одновременно в признак CF и в конец/начало. ПДПшным ROL/ROR полностью соответствует интеловские RCR/RCL, которые крутят биты через CF. Так вот крутить двойное слово надо парами команд SAL/SAR (соответствует ПДПшным ASL/ASR) + RCL/RCR. Сначала смещаем арифметическим сдвигом первую часть, выталкивая бит в признак CF, а затем, крутя вторую половину двойного слова, мы вытесненный бит заводим во вторую часть и выталкиваем в CF бит из второй же. А ROL/ROR будет вытесненный бит крутить внутри второй части, что неверно. И при нечетном регистре получится как раз в финале RCL/RCR.
-
? Дмитрий - 02.10.2018 09:05
Упустил момент с одинаковыми частями при нечетном регистре. Да, получается чистый интеловский ROL/ROR. Отлично, фактически еще одна команда в пределах другой.
-
? Дмитрий - 02.10.2018 09:22
Кстати, в коде в gid - 29.09.2018 09:36 последние две строки справедливы для ПРАВОГО сдвига, ибо результат будет в МЛАДШЕЙ части, а для ЛЕВОГО результат будет в СТАРШЕЙ части. Поэтому запись результата нужна отдельно для каждого сдвига.
-
? svinka@ - 04.10.2018 00:16
реализация из simh
¤
case 3: /* ASHC */
if (!CPUO (OPT_EIS)) {
setTRAP (TRAP_ILL);
break;
}
src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
src2 = src2 & 077;
sign = GET_SIGN_W (R[srcspec]);
src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1];
if (src2 == 0) { /* [0] */
dst = src;
V = C = 0;
}
else if (src2 <= 31) { /* [1,31] */
dst = ((uint32) src) << src2;
i = (src >> (32 - src2)) | (-sign << src2);
V = (i != ((dst & 020000000000)? -1: 0));
C = (i & 1);
}
else if (src2 == 32) { /* [32] = -32 */
dst = -sign;
V = 0;
C = sign;
}
else { /* [33,63] = -31,-1 */
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
V = 0;
C = ((src >> (63 - src2)) & 1);
}
i = R[srcspec] = (dst >> 16) & 0177777;
dst = R[srcspec | 1] = dst & 0177777;
N = GET_SIGN_W (i);
Z = GET_Z (dst | i);
break;
-
? Дмитрий - 04.10.2018 13:33
В дополнение к ASH. Есть простейший алгоритм формирования таблицы для подсчета CRC32.
¤
unsigned long crc_table[256];
¤
void make_crc_table()
{
for ( unsigned long i = 0; i < 256; i++ )
{
unsigned long r = i;
for ( unsigned long j = 0; j < 8; j++ )
{
if (r & 1)
r = (r >> 1) ^ 0xEDB88320;
else
r >>= 1;
}
crc_table[i] = r;
}
}
¤
pdp11-gcc для сдвига вставляет ASH #-1 для реализации SHR, что неверно - SHR логический сдвиг, а ASH арифметический. Оставим это на совести gcc. Так вот, переведя его на асм, столкнулся с проблемкой, а именно - если ASH реализовать на х86 SAL/SAR (полный аналог ASL/ASR), то таблица формируется неверно (во всех 256 значениях самый старший байт в тетраде неправильный, а остальные 3 правильные - налицо баги сдвига, как раз 8 бит). Если же SAL/SAR заменить в реализации ASH на SHL/SHR (для проверки), то алгоритм работает как часы и таблица формируется абсолютно верно. Хорошо. Убрал ASH и сделал связку CLC+ROR (по сути тот же SHR) - сдвиг вправо с очисткой самого старшего бита. Однако таблица опять неверна - опять самый старший байт тетрады неверный. Полез в реализацию ROR (взята из эмулятора gid'а) - все верно, реализация правильная. Для очистки совести заменил на асм-реализацию:
¤
...
mov cl,byte ptr[SignC] // берем текущий признак С из булевой переменной (0 - false, 1 - true)
rcr cl // выталкиваем бит 0 во флаг CF
rcr eax // крутим данные, вталкивая из CF в 31 бит EAX и вытесняя 0 бит в CF (ROR)
... // далее тащим в признаки новые значения из флагов х86
¤
поскольку перед ROR я делаю CLC, то SignC всегда false (cl=0) и после "rcr cl" CF всегда 0. Однако алгоритм опять не работает и опять старший байт тетрады результата неверный. Причем он отличается от того, который получен в реализации ROR gid'а.
¤
Первый элемент равен 0
¤
верное значение 2 элемента: 0x77073096
ROR (вариант gid'а): 0x09073096
ROR (asm-вариант с RCR): 0xF5073096
-
? Дмитрий - 04.10.2018 13:35
тьфу, gcc сует ASHC #-1
-
? Дмитрий - 09.10.2018 14:21
С ASHC разобрался, все в норме. Наткнулся еще на одну неточность в описании команды DIV. В описании сказано, что "V устанавливается, если источник (делитель) равен нулю, либо если значение регистра по модулю больше абсолютной величины делителя: в этом случае деление не выполняется, поскольку результат выйдет за разрядную сетку." Это неверно. При таком делении ДЕЛИТЕЛЬ не должен быть больше делимого, а не наоборот.
¤
MOV #25.,R0
CLR R1
DIV #5,R0 ; 25/5
¤
получится 5, хотя по описанию R0 > 5, а значит переполнение. Разве нельзя нацело разделить 25 на 5 без переполнения? А вот наоборот 5/25 - даже знаковый DIV интела вызывает ошибку переполнения. Кстати, "по модулю" равнозначно "абсолютная величина".
- << Форум