Я вижу, раз есть интерес к 1806 надо замутить переходник для него на плату DE0, чтобы тестировать процессор можно было.
Вид для печати
Неплохо было бы. Можно узнать какие глюки починили, а какие остались. Глюка с адресацией @PC уже нет, код 030 исполняется как 020 (RSEL). Возможно уже нет глюка при записи по адресу предвыборки, если адрес записи и PC отличаются разным значением бита 0 (чёт и нечёт). Вот про глюки с записью R7 в EIS и записью CPSW при переполнении в DIV до этого было неизвестно, вскрылось только сейчас.
Ну, и финальная вишенка на торте команд расширенной арифметики - это ASH(C).
По сравнению с MUL и DIV простая до неприличия. Даже проверять не стал.
ASH(C):
- - - Добавлено - - -Код://======================================================================
//
// Команда ASH(C) Rs,Rd
//
//======================================================================
0x3B: ACC=Rs // ACC - счетчик
//----------------------------------------------------------------------
0x1A: // (в данной команде поля Rs и Rd кодируются нестандартно)
EA1=Rd // EA1 - старшее слово (единственное для ASH)
if ASH GOTO 0x27
//---------------------------------------------------------------------- ASHC
0x2A: EA2=Rd|1 // EA2 - младшее слово
//----------------------------------------------------------------------
0x27: if (ACC[5]=0) CTR=ACC // Сдвиг влево
else CTR=~ACC // Сдвиг вправо
// CTR - счетчик итераций 0..31
TLZ=EA1[15] // TLZ - знак старшего слова
//----------------------------------------------------------------------
0x35: // Первая итерация
if LEFT EA1.EA2=EA1.EA2 NZVC // Если сдвиг влево, то первая итерация ничего не делает
else EA1.EA2=EA1.EA2>>1 NZVC
if (CTR=0)
if ASH GOTO 0x0C
else GOTO 0x0E
//----------------------------------------------------------------------
0x35: loop: CTR=CTR-1 // Все последующие итерации
if LEFT EA1.EA2=EA1.EA2<<1 NZVC
else EA1.EA2=EA1.EA2>>1 NZVC // Арифметический сдвиг вправо
if (CTR<>0) GOTO loop
// Влияние на флаги:
// N=EA1[15] (знак результата)
// Если ASHC, и EA1.EA2=0, то Z=1
// Если ASH, и EA1=0, то Z=1
// Иначе Z=0
// Если ASHC RIGHT, то C=ЕА2'[0] (предыдущее значение EA2[0])
// Если ASH RIGHT, то C=ЕА1'[0] (предыдущее значение EA1[0])
// Если ASH(C) LEFT, то C=ЕА1'[15] (предыдущее значение EA1[15])
// Если ASH(C) RIGHT, то V=0
// Если ASH(C) LEFT, то для первой итерации V=0
иначе если хотя бы в одной итерации TLZ^EA1[15]=1, то V=1
if ASH GOTO 0x0C
//---------------------------------------------------------------------- ASHC
0x0E: Rd=EA1 // Rd=ЕА1 - старшее слово
//----------------------------------------------------------------------
0x0C: if ASHC Rd|1=EA2 // Rd|1=ЕА2 - младшее слово
if ASH Rd=EA1 // Rd=EA1 - слово для ASH
PLI_REQ // Запросить проверку запросов на прерывание
if X(Rs) or @X(Rs) or (Rs=R7) // Если использовали адресацию по R7, то
GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
else // Иначе
GOTO 0x01 // Перейти на команду выборки следующей инструкции
Из интересненького: как видно из алгоритма, сдвиг 32-битного слова всего на 8 тактов медленнее, чем сдвих 16-битного, независимо от числа итераций.
Поэтому, если требуется работа с большими данными, лучше оперировать сразу с 32-битными словами.
Значение 0100 0000 0000 0000 сдвигаю влево на три разряда. При первом сдвиге фиксируется изменение знака, результат 1000 0000 0000 0000. При втором сдвиге фиксируется изменение знака, результат 0000 0000 0000 0000. При третьем сдвиге изменения знака нет, но флаг V должен стоять.
Проверил на реале.
После исполнения установлены биты Z и V.Код:1000 012701 MOV #40000,R1
1002 040000
1004 012700 MOV #3,R0
1006 000003
1010 072100 ASH R0,R1
1012 106702 MFPS R2
- - - Добавлено - - -
А не влияет ли наличие RS-триггера на исполнение других команд EIS?
Двухоперандные команды с регистром источником формата ALU Rs,dd.
В эту же группу входят команды расширенной арифметики формата EALU Rd,ss.
MOV(B), BIS(B), BIC(B), ADD, SUB, CMP(B), BIT(B), XOR,
MUL, DIV, ASH, ASHC:
Код://======================================================================
//
// Oперации с двумя операндами вида Rs,nn
//
// MOV(B), BIS(B), BIC(B), ADD, SUB, CMP(B), BIT(B),
// XOR, MUL, DIV, ASH, ASHC
//
// step=1 для байтовых команд, если dd<>R6 и dd<>R7
// step=2 для всх остальных команд
//
// Циклы шины IO_X001 для:
//
// CMP(B), BIT(B), MUL, DIV, ASH, ASHC
// Read (IO_RD, IO_IN) - Инициировать цикл чтения шины в регистр BRD
//
// MOV:
// Write (IO_WR) - Инициировать цикл записи BRD на шину
//
// MOVB, BIS(B), BIC(B), ADD, SUB, XOR:
// R-M-W (IO_RD, IO_WR, IO_IN) - Инициировать цикл чтения шины в регистр BRD
// с последующим циклом записи по готовности BRD
//
//======================================================================
0x2B: RS=Rs
//----------------------------------------------------------------------
0x17: if (Rn) RA=Rn IO_X001 // Инициировать цикл шины
Rn=Rn
GOTO 0x33
if (Rn)+ and (RI0=0) // Если Rn<>R7
RA=Rn IO_X001 // Инициировать цикл шины
Rn=Rn+step
GOTO 0x33
if (Rn)+ and (RI0=1) and (IX0=1) // Если Rn=R7, и работа со словом
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
BRD=BIR IO_X001 // Подготовить, но не начинать цикл шины
GOTO 0x33
if (Rn)+ and (RI0=1) and (IX0=0) // Если Rn=R7, и работа с байтом
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
RA=PC1-2 IO_X001 // Инициировать цикл шины
GOTO 0x33
if -(Rn) Rn=Rn-step
RA=Rn IO_X001 // Инициировать цикл шины
GOTO 0x33
if @-(Rn) Rn=Rn-2
RA=Rn IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD
GOTO 0x22
if @(Rn)+ and (RI0=0) // Если Rn<>R7
Rn=Rn+2
RA=Rn IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD
GOTO 0x22
if @(Rn)+ and (RI0=1) // Если Rn=R7
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
RA=BIR IO_X001 // Инициировать цикл шины
GOTO 0x33
if X(Rn) PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
RA=Rn+BIR IO_X001 // Инициировать цикл шины
GOTO 0x33
if @X(Rn) PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
RA=Rn+BIR IO_RD, IO_IN // Инициировать цикл чтения шины в регистр BRD
//---------------------------------------------------------------------- Прочитана ячейка с адресом операнда
0x22: PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
WAIT_BRD // Ожидание готовности чтения BRD
RA=BRD IO_X001 // Инициировать цикл шины
ENABLE_CACHE // Разрешить кэш
//---------------------------------------------------------------------- Операнд прочитан из памяти, если цикл шины Read или RMW
0x33: WAIT_BRD // Ожидание готовности чтения BRD
if MUL,DIV,ASH(C)
ACC=BRD
if MUL GOTO 0x18 // Если MUL, то перейти на шаг 0x18 микропрограммы выполнения умножения
if DIV GOTO 0x1A // Если DIV, то перейти на шаг 0x1A микропрограммы выполнения деления
if ASH(C) GOTO 0x1A // Если ASH(C), то перейти на шаг 0x1A микропрограммы выполнения циклического сдвига
ALU RS,BRD // Операции ALU из шага 0x3B, в качестве приемника BRD, в качестве источника RS
// Если используется цикл записи Write или RMW, то по записи в BRD, продолжается цикл записи
ENABLE_CACHE // Разрешить кэш
PLI_REQ // Запросить проверку запросов на прерывание
if X(Rn) or @X(Rn) or (Rn=R7) // Если использовали адресацию по R7, то
GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
else // Иначе
GOTO 0x01 // Перейти на команду выборки следующей инструкции
Кстати, а слабо исходники микрокода 1801 сгенерить? А потом собрать своим метаассемблером?
Меня это интересует давно, я не понимал как это сделано. Сейчас, по итогам М4, у меня соображения появились, что микрокод для серии 1801 писался с гораздо более широким выходным словом, на которое навесили нужные мультиплексоры и согласователи для стыковки с АЛУ и потом это все оптимизировали в матрицу машинным способом. Потому что разобрать и проанализировать матрицу - это еще понять можно, но синтез руками - сделать сложно. Так что вероятность процентов 90 что так и было. На момент разработки 1801 метассмеблеры уже были, секционники вовсю проектировались, оптимизировать тоже понятно как, так что это именно оно - недостающее звено. Надо Отрохова и Подорова поспрашивать, как оно реально было.
Тю, я думал тебе оно интересно, ты же вон код вручную разбирал - это как пруд чайной ложкой копать :).
Не, компилируемый исходник это исходник - можно вносить серьезные изменения и дополнения.
Да и вдруг удастся переоптимизировать. Хотя вряд ли, алгоритмам оптимизации типа карт Карно в обед тыщу лет.
У меня интерес исключительно практический - понять в точности, как все работает, чтобы если захочется сделать точный эмулятор. А может и не захочется. У нас УКНЦ-шников на форуме все меньше и меньше. К тому времени, пока его напишешь, и оставшиеся 3 человека пропадут)
- - - Добавлено - - -
Для понимания принципа работы, изменения вносить не нужно.
Да и зачем изменения? Микрокод в высшей степени оптимален. А исправлять ошибки в нем - нет смысла, ибо потеряется совместимость с оригиналом.
И, наконец, финальная вишенка на торте описания микрокода ВМ2 - это команды с двумя операндами, расположенными в памяти.
MOV(B), BIS(B), BIC(B), ADD, SUB, CMP(B), BIT(B):
Больше в микрокоде ничего нет, так что на этом, это самое, мои полномочия всё... закончены)Код://======================================================================
//
// Oперации с двумя операндами вида ss,dd
//
// MOV(B), BIS(B), BIC(B), ADD, SUB, CMP(B), BIT(B)
//
// step=1 для байтовых команд, если dd<>R6 и dd<>R7
// step=2 для всх остальных команд
//
// RI2=1, если адресация ss: (R7), (R7)+, -(R7), @(R7)+, @-(R7), X(Rn), @X(Rn)
//
// Циклы шины IO_X001 для:
//
// CMP(B), BIT(B)
// Read (IO_RD, IO_IN) - Инициировать цикл чтения шины в регистр BRD
//
// MOV:
// Write (IO_WR) - Инициировать цикл записи BRD на шину
//
// MOVB, BIS(B), BIC(B), ADD, SUB:
// R-M-W (IO_RD, IO_WR, IO_IN) - Инициировать цикл чтения шины в регистр BRD
// с последующим циклом записи по готовности BRD
//
//======================================================================
0x0F: if (Rn) RA=Rs IO_RD, IO_IN // Инициировать цикл чтения шины
Rs=Rs
if (Rn)+ and (IX1=0) // Если Rn<>R7
RA=Rs
Rs=Rs+step
if (Rn)+ and (IX1=1) and (IX0=1) // Если Rn=R7, и работа со словом
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
ACC=Rs // Пустая операция
// Чтение BRD не инициируется, т.к. в нем уже и так находится требуемое слово
if (Rn)+ and (IX1=1) and (IX0=0) // Если Rn=R7, и работа с байтом
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
ACC=PC1-2 // ACC=PC1-2 (коррекция, т.к. PC1 опережает реальное значение R7 на 2)
RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины
if -(Rn) Rs=Rs-step
RA=Rs IO_RD, IO_IN // Инициировать цикл чтения шины
if @(Rn)+ and (IX1=0) // Если Rn<>R7
RA=Rs IO_RD, IO_IN // Инициировать цикл чтения шины
Rs=Rs+2
GOTO 0x32
if @(Rn)+ and (IX1=1) // Если Rn=R7
WAIT_BRD // Ожидание готовности чтения BRD (на самом деле BIR)
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
// Фактически PC1=PC1+2
ACC=BIR
RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины
if @-(Rn) Rs=Rs-2
RA=Rs IO_RD, IO_IN // Инициировать цикл чтения шины
GOTO 0x32
if X(Rn) WAIT_BRD // Ожидание готовности чтения BRD (на самом деле BIR)
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
ACC=Rs+BIR
RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины
if @X(Rn) WAIT_BRD // Ожидание готовности чтения BRD (на самом деле BIR)
PC1=PC2 DISABLE_CACHE // Запретить кэш и включить режим использования BIR как данных
ACC=Rs+BIR
RA=ACC
GOTO 0x32
if (dd=Rn) and (RI2=0) // Если приемник - регистр и ss не использует R7
GOTO 0x13
if (dd=Rn) and (RI2=1) // Если приемник - регистр и ss использует R7
GOTO 0x12
else GOTO 0x03 // Иначе приемник - память
//---------------------------------------------------------------------- Чтение операнда из памяти
0x32: WAIT_BRD // Ожидание готовности чтения BRD
ACC=BRD
RA=ACC IO_RD, IO_IN // Инициировать цикл чтения шины
if (dd=Rn) and (RI2=0) // Если приемник - регистр и ss не использует R7
GOTO 0x13
if (dd=Rn) and (RI2=1) // Если приемник - регистр и ss использует R7
GOTO 0x12
else GOTO 0x03 // Иначе приемник - память
//---------------------------------------------------------------------- Приемник - регистр, ss использует R7
0x12: WAIT_BRD // Ожидание готовности чтения BRD
RS=BRD
//---------------------------------------------------------------------- Кэширование следующей команды
0x10:
RA=PC2 IO_RD, IO_IN, IO_RCD // Инициировать цикл чтения шины в регистр BIR и BRD одновременно (кеширование следующей команды/данных)
PC1=PC2 // Фактически имитация PC1=PC+2
PC2=PC2+2
//---------------------------------------------------------------------- Приемник - регистр
0x13:
if (RI2=0) WAIT_BRD // Если ss не использует R7, то oжидание готовности чтения BRD
ALU BRD,Rd // Операции ALU из шага 0x3B, в качестве приемника Rd, в качестве источника BRD
else // Иначе ss использует R7
ALU RS,Rd // Операции ALU из шага 0x3B, в качестве приемника Rd, в качестве источника RS
endif
PLI_REQ // Запросить проверку запросов на прерывание
if (Rd=R7) // Если Rd=R7, то
GOTO 0x21 // Перейти на команду выборки следующей некэшированной инструкции
else // Иначе
GOTO 0x01 // Перейти на команду выборки следующей инструкции
//---------------------------------------------------------------------- Приемник - память
0x03: WAIT_BRD // Ожидание готовности чтения BRD
RS=BRD
if (RI2=0) GOTO 0x17 // Если ss не использует R7, то перейти на шаг 0x17 операции с двумя операндами
//---------------------------------------------------------------------- ss использует R7
0x16: // Кэширование следующей команды (для того, чтобы адресация dd по R7 работала корректно)
RA=PC2 IO_RD, IO_IN, IO_RCD // Инициировать цикл чтения шины в регистр BIR и BRD одновременно (кеширование следующей команды/данных)
PC1=PC2 // Фактически имитация PC1=PC+2
PC2=PC2+2
GOTO 0x17 // Перейти на шаг 0x17 операции с двумя операндами
//----------------------------------------------------------------------
Скрытый текст
Titus, вы же сами об этом спрашивали полмесяца назад - здесь.
По ссылке я увидел только этот тест, но он тестирует компаратор адреса.
Читать надо внимательно, там ссылка на страницу с тестами - здесь. Там много чего есть.
- - - Добавлено - - -
А вот и конкретные тесты.
Я так понял, что описание глюка здесь.
Вот тут у меня полный набор тестов для предвыборки ВМ2, включая "суперглюк" с его описанием.
Действительно, забыл описать.
JMP Rn, JSR Rs,Rd:
Код://======================================================================
//
// Команды JMP Rn, JSR Rs,Rd
//
//======================================================================
0x30: NO ALU PI_STB VEC=0x04 RI=100 // Управление: запрос программного прерывания по вектору 0x04 в режиме USER
GOTO 0x01 // Перейти на команду выборки следующей инструкции
0x02 - дублирует шаг 0x03
0x06 - не используется
0x07 - это TRAP10_7, TRAP10_40, TRAP10_6500, TRAP10_6600
0x0A - не используется
0x0B - не используется
0x14 - отсутствует
0x15 - отсутствует
0x1B - дублирует шаг 0x3B
0x24 - отсутствует
0x29 - дублирует шаг 0x09
0x3A - не используется
0x3F - не используется
Замечу, что просьба к @Vslav'у о диаграммах из предпредыущего поста все еще в силе)
Еще раз сгенерил базовую таблицу преддекодера и не нашел в ней ни одной записи совпадающей с 0xF000 (TRAP 170000):
Код:Instruction NA ___ MOP
FEDCBA9876543210 543210 01 RTT BYTE IX2
00: 0000000000000110 000000 00 1 RTT
12: 000000001.000... 110000 00 1 RTS, SWAB Rn
34: 00000000.1...... 010000 00 1 JMP, SWAB
36: .000110111...... 010000 00 1 SXT, MFPS
30: 1000110100...... 010000 01 1 MTPS
37: 0000100......... 010000 11 1 JSR
33: .0001100........ 010000 00 1 ROR(B), ROL(B), ASR(B), ASL(B)
42: .000101......... 010000 00 1 CLR(B), COM(B), INC(B), DEC(B), NEG(B), ADC(B), SBC(B), TST(B)
32: .0000..00....... 000000 11 HALT, WAIT, RTI, BPT, IOT, RESET, RTT, TRAP10_7, START, STEP, RSEL, MFUS, RCPC, RCPS, CODE30, MTUS, WCPC, WCPS, TRAP10_40, JMP, BNE(!), BGE(!), BGT(!), BPL(!), BHI(!), BVC(!), BCC(!)
13: 0000.0.000...... 000000 10 HALT, WAIT, RTI, BPT, IOT, RESET, RTT, TRAP10_7, START, STEP, RSEL, MFUS, RCPC, RCPS, CODE30, MTUS, WCPC, WCPS, TRAP10_40, BNE(!), JSR(!), CLR
26: 0001............ 000000 10 MOV
28: 0000..01........ 000000 10 BR, BLT, MARK, TRAP10_6500, TRAP10_6600, SXT
16: .000101111...... 000000 01 TST(B)
47: .01............. 001000 01 CMP(B), BIT(B)
43: 01110........... 101100 01 MUL, DIV, ASH, ASHC
01: 1000110100000... 100000 00 MTPS Rn
08: .000110111000... 100000 00 SXT Rn, MFPS Rn
11: .0001100..000... 100000 00 ROR(B) Rn, ROL(B) Rn, ASR(B) Rn, ASL(B) Rn
25: .000101...000... 100000 00 CLR(B) Rn, COM(B) Rn, INC(B) Rn, DEC(B) Rn, NEG(B) Rn, ADC(B) Rn, SBC(B) Rn, TST(B) Rn
06: 0111100...000... 010000 00 XOR Rs,Rd
04: 01110.....000... 010000 00 MUL Rs,Rd, DIV Rs,Rd, ASH Rs,Rd, ASHC Rs,Rd
09: .0.1000...000... 010000 00 MOV(B) Rs,Rd, BIT(B) Rs,Rd
14: .10.000...000... 010000 00 BIC(B) Rs,Rd, BIS(B) Rs,Rd
23: ..10000...000... 010000 00 CMP(B) Rs,Rd, ADD Rs,Rd, SUB Rs,Rd
15: 0000000000000011 000010 00 BPT
17: 0000000000000.01 000010 00 WAIT, RESET
10: 0000000000001... 000010 00 START, STEP
03: 000000000001.... 000010 00 RSEL, MFUS, RCPC, RCPS, CODE30, MTUS, WCPC, WCPS
02: 0000110100...... 000010 00 MARK
07: 01111010000..... 000010 00 FIS
05: 00000000101..... 000010 00 CLx, SEx
45: ..01............ 001000 00 MOV(B), BIS(B)
46: .1.0............ 001000 00 BIC(B), ADD, SUB
21: .0000..0000....0 000010 00 HALT, RTI, IOT, RTT, START(!), STEP(!), RSEL, RCPC(!), RCPS(!), CODE30, WCPC(!), WCPS(!), BNE(!), BGE(!), BGT(!), BPL(!), BHI(!), BVC(!), BCC(!)
18: 10000000........ 000001 00 BPL
24: 1000.00......... 000010 00 BPL, BMI, EMT, TRAP
22: .0000001........ 000011 00 BR, BMI
29: .000001......... 000011 00 BNE, BEQ, BHI, BLOS
31: .00001.......... 000011 00 BGE, BLT, BGT, BLE, BVC, BVS, BCC, BCS
19: 0000100...000... 100111 00 JSR Rs,Rd
20: 0000000001000... 100111 00 JMP Rn
27: 0111111......... 001010 00 SOB
39: 0111100......... 101100 00 XOR
35: .10.000......... 100100 00 BIC(B) Rs,dd, BIS(B) Rs,dd
40: .0.1000......... 100100 00 MOV(B) Rs,dd, BIT(B) Rs,dd
41: ..10000......... 100100 00 CMP(B) Rs,dd, ADD Rs,dd, SUB Rs,dd
38: 1.0............. 000000 00 1 BPL, BMI, BHI, BLOS, BVC, BVS, BCC, BCS, EMT, TRAP, MTPS, TRAP10_106500, TRAP10_106600, MFPS, TRAP10_107000
44: 10.............. 000000 00 1 BPL, BMI, BHI, BLOS, BVC, BVS, BCC, BCS, EMT, TRAP, MTPS, TRAP10_106500, TRAP10_106600, MFPS, TRAP10_107000