Да, все так PC и CPSW обновляются всегда, кроме случаев когда:
1. PSW[8]=1, PSW[7]=1
2. Кроме случаев работы с константой (сделано специально для удержания PC и CPSW в обработчике прерывания HALT).
3. Также есть отдельный случай влияющий на копирование PC1->PC, но я с ним пока не разбирался.
- - - Добавлено - - -
Продолжение банкета:
RSEL:
Код://====================================================================== // // Команда RSEL (000020) (HALT) // //====================================================================== 0x05: ACC=ACC IO_RD, IO_IN, IO_SEL // Инициировать цикл чтения безадресного регистра в регистр BRD //---------------------------------------------------------------------- (совмещено с MFUS, и частично с RTI, RTT) 0x27: WAIT_BRD // Ожидание готовности чтения BRD R0=BRD PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
MFUS:
Код://====================================================================== // // Команда MFUS (000021) (HALT) // //====================================================================== 0x05: RA=R5 IO_RD, IO_IN, IO_ALT // Инициировать альтернативный цикл чтения шины в регистр BRD // Отличие от обычного цикла в том, что вывoд SEL=~PSW[8] R5=R5+2 //---------------------------------------------------------------------- (совмещено с RSEL, и частично с RTI, RTT) 0x27: WAIT_BRD // Ожидание готовности чтения BRD R0=BRD PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
MTUS:
Код://====================================================================== // // Команда MTUS (000031) (HALT) // //====================================================================== 0x05: RA=R5=R5-2 IO_WR, IO_ALT // Инициировать альтернативный цикл записи BRD на шину (SEL=~PSW[8]) //---------------------------------------------------------------------- 0x27: BRD=R0 PLI_REQ // Инициилизировать BRD и продолжить цикл записи // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
WCPC:
Код://====================================================================== // // Команда WCPC (000032-000033) (HALT) // //====================================================================== 0x05: PC=R0 PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
WCPS:
- - - Добавлено - - -Код://====================================================================== // // Команда WCPS (000034-000037) (HALT) // //====================================================================== 0x05: CPSW=R0 PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
RCPC:
Код://====================================================================== // // Команда RCPC (000022-000023) (HALT) // //====================================================================== 0x05: R0=PC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
RCPS:
- - - Добавлено - - -Код://====================================================================== // // Команда RCPS (000024-000027) (HALT) // //====================================================================== 0x05: R0=CPSW PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
MARK:
- - - Добавлено - - -Код://====================================================================== // // Команда MARK (0063NN) // //====================================================================== 0x05: ACC=PC1+((IR&0x003F)*2) //---------------------------------------------------------------------- 0x35: R6=ACC //---------------------------------------------------------------------- 0x09: PC1=PC2=R5 //---------------------------------------------------------------------- 0x31: RA=R6 IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD R6=R6+2 //---------------------------------------------------------------------- 0x19: WAIT_BRD // Ожидание готовности чтения BRD R5=BRD PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
CLx:
Код://====================================================================== // // Команда CLx (000240-000257) // //====================================================================== 0x05: ACC=IR&0x000F // Совмещено с SEx //---------------------------------------------------------------------- 0x27: PSW=PSW&~ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
SEx:
- - - Добавлено - - -Код://====================================================================== // // Команда SEx (000260-000277) // //====================================================================== 0x05: ACC=IR&0x000F // Совмещено с CLx //---------------------------------------------------------------------- 0x27: PSW=PSW|ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
BRA, Bcc:
Код://====================================================================== // // Команда BRA, Bcc (000400-003777) // (100000-103777) // //====================================================================== 0x04: // На входе уже проверенные условия (BRA), сделанные во время команды выборки кода инструкции (0x01) if (BRA=1) // Если BRA=1 (условия совпали) PC1=PC2=PC1+SIGNEXT((IR&0x00FF)<<1) PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции else // Иначе ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
Последний раз редактировалось Titus; 26.11.2020 в 20:25.
Alex_K(24.11.2020)
Одно из самых таинственных действий процессора 1801ВМ2, скрытое под покровами микрокода - это выборка инструкции и обработка прерываний.
Выборка иструкции:
Код://====================================================================== // // Пустая команда (не используется?) // //====================================================================== 0x00: ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции //====================================================================== // // Команда выборки некэшированной инструкции // // Входные данные: PC1 - указывает на адрес инструкции // //====================================================================== 0x21: if (RI=001) // Если нет запроса на прерывание, то RA=PC1 IO_RD, IO_CMD // Инициировать цикл чтения шины в регистр BRI (инициализация кэширования инструкции) PC1=PC2=PC1+2 GOTO 0x01 // Перейти на команду выборки следующей инструкции if (RI=000) // Если режим WAIT, то ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции if (RI2=1) // Если есть запрос на прерывание, то ACC=ACC IO_RD, IO_IN, IO_SEL // Инициировать цикл чтения безадресного регистра в регистр BRD GOTO 0x11 // Перейти на команду обработки прерывания //====================================================================== // // Команда выборки кэшированной инструкции // // Входные данные: PC2 - указывает на адрес инструкции + 2 // PC1 - указывает на адрес инструкции // или на адрес инструкции + 2 // //====================================================================== 0x01: if ((RI=001) & IX1=0) // Если нет запроса на прерывание, и BIR действительный, то SET_CEND // Если в BIR еще нет слова текущей инструкции, то ждать готовности BIR, // затем преддекодер декодирует инструкцию и устанавливает начальные параметры для микропрограммы BRA_REQ // Запросить проверку условий по значениям BIR и PSW, которые могут быть // использованы, если следующей командой будет условный переход IO_RCD1 // Особое управление блоком таймаута RA=PC2 IO_RCD // Инициировать цикл чтения шины в регистр BIR и BRD одновременно (кеширование следующей команды/данных) PC1=PC2 // Фактически имитация PC1=PC+2 PC2=PC2+2 GOTO 0x00 // На самом деле переход осуществляется на первую команду новой инструкции if ((RI=001) & IX1=1) // Если нет запроса на прерывание, и BIR недействительный, то PC1=PC2=PC1-2 GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции if (RI=000) // Если режим WAIT, то ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции if (RI2=1) // Если есть запрос на прерывание, то ACC=ACC IO_RD, IO_IN, IO_SEL // Инициировать цикл чтения безадресного регистра в регистр BRD GOTO 0x11 // Перейти на команду обработки прерывания
Обработка прерывания:
Код://====================================================================== // // Обработка запроса на прерывание // //====================================================================== 0x11: if (RI1=0) // Если запрос на прерывание в режиме USER, то WAIT_BRD // Ожидание готовности чтения BRD PSW=0 GOTO 0x3E // Перейти на обработку прерывания в режиме USER if (RI1=1) // Если запрос на прерывание в режиме HALT WAIT_BRD // Ожидание готовности чтения BRD PSW=0xFFEF //---------------------------------------------------------------------- 0x3C: // Обработка прерывания HALT. В регистре BRD находится считанный безадресный регистр BRD.L=0 //---------------------------------------------------------------------- 0x1D: ACC=BRD+вектор // Вектор прерывания устанавливается блоком запроса прерываний RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD GOTO 0x20 // Перейти на продолжение обработки прерываний //---------------------------------------------------------------------- 0x3Е: // Обработка прерываний USER RA=R6=R6-2 IO_WR, IO_CMD // Инициировать цикл записи BRD на шину //---------------------------------------------------------------------- 0x1C: BRD=CPSW // Инициилизировать BRD и продолжить цикл записи //---------------------------------------------------------------------- 0x2E: RA=R6=R6-2 IO_WR, IO_CMD // Инициировать цикл записи BRD на шину //---------------------------------------------------------------------- 0x36: BRD=PC // Инициилизировать BRD и продолжить цикл записи //---------------------------------------------------------------------- 0x34: if (RI0=0) // Если не векторное прерывание (VIRQ), то ACC=вектор // Вектор прерывания устанавливается блоком запроса прерываний RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD GOTO 0x20 // Перейти на продолжение обработки прерываний else // Иначе векторное прерывание (VIRQ) ACC=ACC IO_RD, IO_IN, IO_IAK // Инициировать цикл чтения вектора прерывания IAK в регистр BRD //---------------------------------------------------------------------- 0x2F: WAIT_BRD // Ожидание готовности чтения BRD RA=ACC=BRD IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD //---------------------------------------------------------------------- 0x20: // Продолжение обработки прерывания общее для всех WAIT_BRD // Ожидание готовности чтения BRD PC1=PC2=BRD //---------------------------------------------------------------------- 0x3D: ACC=ACC+2 // ACC - вектор прерывания + 2 RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD //---------------------------------------------------------------------- 0x26: // Ожидание готовности чтения BRD if (RI=11x) // Если прерывание в режиме HALT/начальный пуск, то PSW=BRD else // Иначе прерывание в режиме USER PSW.B=BRD //---------------------------------------------------------------------- 0x39: NO ALU PI_STB CLR_WAIT RI=000 // Управление: отменить режим WAIT (влияет на режим флага Т?) //---------------------------------------------------------------------- (Общий шаг для многих команд) 0x25: ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
Последний раз редактировалось Titus; 25.11.2020 в 20:46.
Следующая часть Мерлезонского балета.
Очень увлекательное, хотя, и требующее времени и внимательности, занятие - восстанавливать микрокод.
Но, тут как с кошечкой в пылесосе, главное втянуться
RTS:
Код://====================================================================== // // Команда RTS (000200-000207) // //====================================================================== 0x37: PC1=PC2=Rn //---------------------------------------------------------------------- 0x28,0x38: RA=R6 IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD R6=R6+2 //---------------------------------------------------------------------- 0x1F: WAIT_BRD // Ожидание готовности чтения BRD Rn=BRD PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
FIS:
Код://====================================================================== // // Команда FIS (075000-075037) // //====================================================================== 0x05: ACC=ACC IO_RD, IO_IN, IO_SEL // Инициировать цикл чтения безадресного регистра в регистр BRD //---------------------------------------------------------------------- 0x27: WAIT_BRD // Ожидание готовности чтения BRD ACC.B=BRD GET_STATE N=0 // Если N=0, то BRA=1, иначе BRA=0 //---------------------------------------------------------------------- 0x35: if (BRA=1) // Если BRA=1 (в прошлой команде N=0) NO ALU PI_STB VEC=0x08 RI=110 // Управление: запрос программного прерывания по вектору 0x08 в режиме HALT GOTO 0x01 // Перейти на команду выборки следующей инструкции else // Иначе NO ALU PI_STB VEC=0x08 RI=100 // Управление: запрос программного прерывания по вектору 0x08 в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции
WAIT:
Код://====================================================================== // // Команда WAIT (000001) // //====================================================================== 0x05: NO ALU PI_STB WAIT RI=000 // Управление: установить режим WAIT, сообщить о режиме WAIT блоку прерываний GOTO 0x01 // Перейти на команду выборки следующей инструкции
RESET:
Код://====================================================================== // // Команда RESET (000005) // //====================================================================== 0x05: NO ALU PI_STB INIT RI=010 // Управление: инициировать INIT //---------------------------------------------------------------------- (Общий шаг для многих команд) 0x25: ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
HALT:
Код://====================================================================== // // Команда HALT (000000) // //====================================================================== 0x05: NO ALU PI_STB VEC=0x78 RI=110 // Управление: запрос программного прерывания по вектору 0x78 в режиме HALT GOTO 0x01 // Перейти на команду выборки следующей инструкции
Все однотипные программные прерывания:
USER: RSEL, MFUS, RCPC, RCPS, CODE030, MTUS, WCPC, WCPS, START, STEP
BPT, IOT, EMT, TRAP:
Код://====================================================================== // // Команды // USER: RSEL, MFUS, RCPC, RCPS, CODE030, MTUS, WCPC, WCPS, START, STEP // TRAP10_7, TRAP10_40, TRAP10_6500, TRAP10_6600 // //====================================================================== 0x05: NO ALU PI_STB VEC=0x08 RI=100 // Управление: запрос программного прерывания по вектору 0x08 в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции //====================================================================== // // Команда BPT (000003) // //====================================================================== 0x05: NO ALU PI_STB VEC=0x0C RI=100 // Управление: запрос программного прерывания по вектору 0x0C в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции //====================================================================== // // Команда IOT (000004) // //====================================================================== 0x05: NO ALU PI_STB VEC=0x10 RI=100 // Управление: запрос программного прерывания по вектору 0x10 в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции //====================================================================== // // Команда EMT (104000-104377) // //====================================================================== 0x05: NO ALU PI_STB VEC=0x18 RI=100 // Управление: запрос программного прерывания по вектору 0x18 в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции //====================================================================== // // Команда TRAP (104400-104777) // //====================================================================== 0x05: NO ALU PI_STB VEC=0x1C RI=100 // Управление: запрос программного прерывания по вектору 0x1C в режиме USER GOTO 0x01 // Перейти на команду выборки следующей инструкции
Последний раз редактировалось Titus; 26.11.2020 в 21:04.
Alex_K(27.11.2020)
Как ни странно, все служебные команды кончились, и начались математическо-логические.
Однооперандные с регистровой адресацией Rn:
INC(B), DEC(B), CLR(B), NEG(B), COM(B), ADC(B), SBC(B),
ASR(B), ROR(B), ASL(B), ROL(B), TST(B), SWAB, SXT, MFPS:
Код://====================================================================== // // Математическо-логические операции с одним операндом // и регистровой адресацией Rn // // INC(B), DEC(B), CLR(B), NEG(B), COM(B), ADC(B), SBC(B), // ASR(B), ROR(B), ASL(B), ROL(B), TST(B), SWAB, SXT, MFPS // //====================================================================== 0x37: if INC(B) Rn(.B)=Rn+1 VZN if DEC(B) Rn(.B)=Rn+~1+1 VZN if CLR(B) Rn(.B)=Rn&0 VZNC if NEG(B) Rn(.B)=~Rn+1 VZNC if COM(B) Rn(.B)=~Rn^0 VZNC if ADC(B) Rn(.B)=Rn+C VZNC if SBC(B) Rn(.B)=Rn+~C+1 VZNC if ASR(B) Rn(.B)=(Rn^0)>>1 VZNC if ROR(B) Rn(.B)=((Rn^0)>>1)|(C<<7) VZNC if ASL(B) Rn(.B)=(Rn^0)<<1 VZNC if ROL(B) Rn(.B)=((Rn^0)<<1)|C VZNC if TST(B) ACC(.B)=Rn^0 VZNC if SWAB Rn=SWAB(Rn^0) VZNC if SXT if (N) Rn=0^0xFFFF VZNC else Rn=0^0 VZN if MFPS Rn=SIGNEXT(PSW) VZN endif PLI_REQ // Запросить проверку запросов на прерывание if (Rn=R7) GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции else GOTO 0x01 // Перейти на команду выборки следующей инструкции
MTPS Rn
Непонятно и специфически устроена команда MTPS, хотя я и догадываюсь почему.Код://====================================================================== // // Команда MTPS Rn (1064SS) // //====================================================================== 0x37: PSW.B=Rn Бит T не изменяется //---------------------------------------------------------------------- 0x18,0x38: PI_STB RI=001 // Управление: нет запроса на прерывание (не имеет эффекта, т.к. следующая команда перезапишет RI) //---------------------------------------------------------------------- 0x08 ACC=ACC PLI_REQ // Запросить проверку запросов на прерывание GOTO 0x01 // Перейти на команду выборки следующей инструкции
Дело в том, что модификация бита T в регистре PSW управляется отдельно, и одним из условий, позволяющем не трогать бит Т является /NA=0. Или, иными словами, чтобы адрес следующей микрокоманды был четным. Однако, если мы закончим обработку стандартно, и перейдем на адрес 0x01, то флаг T тоже изменится. Поэтому сделан обходной маневр по четным адресам, добавляющий 8(!) лишних тактов к инструкции. Вот такие вот костыли на ровном месте, казалось бы. А все из-за экономии места в PLM, и непрофильном использовании бит, относящихся к другим данным, в данном случае к адресу следующей микрокоманды.
- - - Добавлено - - -
Если через 100 лет вас кто-то спросит - дедушка, а почему MFPS выполняется 8 тактов, а MTPS 16? А вы и ответите - бит не хватило, пришлось ехать в Киев через Магадан.
Последний раз редактировалось Titus; 27.11.2020 в 21:01.
Alex_K(27.11.2020)
Начнём:
По данной команде регистр R5 должен увеличиваться на 2.
Ух! Неужто для режима USER PSW становится равным нулю, а в режиме HALT 0177757? Я думал, что только очищается/ставится бит 8. И кстати регистр PSW вроде 9-разрядный.
По моим данным при сохранении в стеке, значение SP всегда уменьшается на 4, даже если при первой записи произошёл TRAP4.
Вроде бы в качестве условия присутствия эмулятора FIS выступает сброшенное значение разряда 7 в SEL.
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Да, 9 разрядов. Остальные незадействованы.
Чтобы очистить/поставить бит 8, нужна константа 0x0100. А ее в блоке констант нет. Гораздо проще все в 0, или все в 0xFFFF установить.
- - - Добавлено - - -
А в чем несостыковка?
Если бит 7 установлен, то то идет прерывание в режиме USER по вектору 0x08 (резервный код).
А если не установлен, то в режиме HALT по вектору SEL+0x08.
- - - Добавлено - - -
Там не может быть уменьшения на 4, т.к. все константы равны 2.
Да и запись в стек идет последовательно. Какой смысл уменьшать его на 4?
- - - Добавлено - - -
Да, все так. Пропустил одну строчку. Исправлю.
Спасибо за проверку)
Так всё таки 0xFFFF или 0xFFEF, т.е. бит T очищен или нет.
А нестыковка в том, какое сравнение делается - словное или байтовое?
По моим опытам получается, что если при первой записи в стек произойдёт TRAP4, то значение SP всегда уменьшается на 4.
Пример: поставим SP равным 0160002. Дадим команду EMT или TRAP. Текущие значения CPC и CPSW сохраняются в стеке. Сперва SP уменьшается на два и в ячейку 0160000 записывается CPSW, запись не удаётся, должен быть TRAP4. TRAP4 происходит, и значения CPC и CPSW пишутся уже в ячейки 0157772 и 0157774. Ячейка 0157776 остаётся нетронутой.
0xFFEF. А точнее, инверсная константа 0x0010.
- - - Добавлено - - -
Не могу сказать, почему это происходит, т.е. еще не изучал блок таймаута. Он навороченный.
- - - Добавлено - - -
Да, байтовое, тоже исправлю.
- - - Добавлено - - -
Если бегло поразмыслить, то скорее всего блок таймаута дает некий фиктивный RPLY, который называется TO_RPLY. Таким образом операция ввода-вывода завершается, и начинается вторая, уменьшающая SP на 2. Но дальше уже все прерывается.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)