;
; Тест ошибки предвыборки по адресации @PC
;
; В процессоре 1801ВМ2 есть ошибка микрокода, наблюдается при следующих условиях:
;	- выполняется двухадресная команда
;	- источник имеет метод адресации @PC (17 восьмеричное)
;	- приемник не использует PC (поле регистра приемника !=7)
;	- приемник не использует дополнительные слова инструкции (E(Rn), @E(Rn))
;	- предвыборка из памяти достаточно медленная (много тактов до RPLY/AR)
;	  и не успевает завершиться до момента обработки выборки источника
;
; В момент выборки источника происходит передача адреса источника из регистра PC 
; в регистр адреса для выполнения транзакции чтения @PC, при этом регистр PC
; выдается на шину X АЛУ, код операции АЛУ равен X (просто транслировать 
; аргумент X на выход) с обратной записью результата в PC/PC1/PC2 (одновременно).
; При этом PC2 получает старое значение PC (PC2 уже был обновлен при запуске
; предыдущей предвыборки PC+2). Если в этот момент предыдущая предвыборка
; не завершена, при окончании команды микрокод не будет рестартовать предвыборку
; кодом ЧК (io_cmd) (чтение команды) и извлечение последующих команд будет
; происходить по неверному отстающему значению PC2. Если же предвыборка успела
; завершиться до модификации PC, то микрокод рестартует новую превыборку по PC2
; с признаком ЧК и далее исполнение команд будет корректным
;
; Предложена и реализована коррекция, при выполнении двухадресных команд
; с методом адресации источника @PC и не использовании PC в приемнике, а также
; отсутствии дополнительных слов в инструкции, блокируется запись в PC2,
; тем самым позволяя корректно продолжать предвыборку. Метод более простой
; и предсказуемый с ограниченной областью действия, по сравнению с модификацией
; микрокода и рестартом предвыборки по признаку ЧК (io_rcd)
; 
;_____________________________________________________________________________
;
		.title	pcbug            	; основной тест команд
		.list	meb			;
						;
		R0	= %0			;
		R1	= %1			;
		R2	= %2			;
		R3	= %3			;
		R4	= %4			;
		R5	= %5			;
		SP	= %6			;
		PC	= %7			;
;_____________________________________________________________________________
;
		npass	= 3			; количество проходов теста
		memlim	= 40000			; лимит тестовой памяти
		trap4	= 4			;
		tps	= 177566		; регистр данных терминала
		tpb	= 177564		; регистр статус терминала
						;
;_____________________________________________________________________________
;
; Специальные команды 1801ВМ2
; Выполняются только в пультовом (halt, psw[8]=1) режиме
;
		start	=  12			; загрузка нового вектора из
						; регистров копий  CPC,  CPSW
						; если нет запросов на
						; прерывание то начинается
						; исполнение инструкции по
						; новому вектору, иначе 
						; происходит выполнение
						; процедуры прерывания
						; аналогично инструкции rti
						;
						; при выполнении этой инструкции
						; бит halt (psw[8]) может быть
						; изменен (взят из вектора)
						;		
		step	= 16			; инструкция step отличается
						; от инструкции start тем, что
						; независимо от наличия
						; запросов на прерывание
						; выполняет первую инструкцию
						; по новому вектору, аналог
						; инструкции rtt
						;
		rsel	= 20			; безадресное чтение, регистр
						; R0 загружается прочитанными
						; данными
						;
		mfus	= 21			; чтение из чужого адресного
						; пространства, в режиме пульта
						; будет читаться адресное
						; пространство пользователя
						; Поскольку в пользовательском 
						; режиме данная инструкция
						; не исполняется, то ее нельзя
						; использовать для доступа к
						; памяти в режима пульта
						;
						; регистр R0 заполняется
						; прочитанным значение по адресу
						; R5, R5 квеличивается на 2
						; (аналогично mov (R5)+, R0)
						;
		rcpc	= 22			; чтение копии PC, в регистр
						; R0 записывается значение копии
						;
		rcps	= 24			; чтение копии PSW, в регистр
						; R0 записывается значение копии
						;
		mtus	= 31			; запись чужого адресного
						; пространства, регистр R5
						; уменьшается на 2, затем
						; содержимое R0 пересылается
						; по адресу в R5 в адресном
						; пространстве пользовательского
						; режима
						;
		wcpc	= 32			; запись регистра копии PC из R0
 		wcps	= 34			; запись регистра копии PSW из R0
;_____________________________________________________________________________
;
		.macro	vect, offset, adr, val	;
		. 	= offset		;
	.if 	nb, <adr>			;
		.word	adr			;
	.iff					;
		.word	.+2			;
	.endc 					;
	.if	nb, <val>			;
		.word	val			;
	.iff            			;
		.word	0			;
	.endc					;
		.endm				;
;_____________________________________________________________________________
;
		.asect      			;
		. = 0				;
						; вектор начального пуска
		vect	0, entry		; для процессора 1801ВМ2
;_____________________________________________________________________________
;
		vect	4			;
		vect	10			;
		vect	14			;
		vect	20, type		; печать строки по iot
		vect	24			;
		vect	30			;
		vect	34			;
		vect	40			;
		vect	44			;
		vect	50			;
		vect	54			;
		vect	60			;
		vect	64			;
		vect	70			;
		vect	74			;
		vect	100			;
		vect	104			;
		vect	110			;
		vect	114			;
		vect	120			;
		vect	124			;
		vect	130			;
		vect	134			;
		vect	140			;
		vect	144			;
		vect	150			;
		vect	154			;
		vect	160			;
		vect	164			;
		vect	170			;
		vect	174			;
;_____________________________________________________________________________
;
		.	= 200			; начальная точка входа в тест
		.blkw	100			;
stack:						;
tebuf:		.blkw	8.			;
entry:		mov	#stack,	SP		;
		mtps	#340			; запретили прерывания
		jmp	tst7			; выбираем нужный тест
						;
;_____________________________________________________________________________
;
tst0:		mov	#1, R0			; prefetch bug test
		mov	#2, R1			;
		mov	#3, R2			;
		mov	#4, R3			;
		mul	R0, R4			;
		mov	@PC, R4			;
		inc	R0			;
		inc	R1			;
		inc	R2			;
		inc	R3			;
		halt				;
;_____________________________________________________________________________
;
tst1:		mov	#1, R0			; prefetch bug test
		mov	#2, R1			;
		mov	#3, R2			;
		mov	#4, R3			;
		mul	R0, R4			;
		mov	@PC, PC			;
1$:		.word	2$			;
		dec	R0			;
		dec	R1			;
		dec	R2			;
		dec	R3			;
		halt				;
2$:		inc	R0			;
		inc	R1			;
		inc	R2			;
		inc	R3			;
		halt				;
;_____________________________________________________________________________
;
tst2:		mov	#1, R0			;
		mov	#2, R1			;
		mov	#3, R2			;
		mov	#4, R3			;
		mul	R0, R4			;
		mov	@PC, 2(R1)		;
		inc	R0			;
		inc	R1			;
		inc	R2			;
		inc	R3			;
		halt				;
;_____________________________________________________________________________
;
tst3:		mov	#1, R0			; проверка одноадресной команды
		mov	#2, R1			; запись в PC/PC1/PC2 при извлечении
		mov	#3, R2			; источника формируется, но микрокод
		mov	#4, R3			; продолжает выполнение с признаком
		mul	R0, R4			; чтение команды, при котором
		tst	@PC			; устанавливается корректное
		inc	R0			; значение регистра PC2 для
		inc	R1			; предвыборки следующей команды
		inc	R2			;
		inc	R3			;
		halt				;

;_____________________________________________________________________________
;
tst4:		br	1$			; тест компаратора адреса предвыборки
		nop				;
		nop				;
		nop				;
1$:		mov	#1, R0			;
		mov	#2, R1			;
		mov	#2$, R2			; записываем по нечетному адресу
		inc	R2			; код инструкции  mov R1, R4
		mov	#010104, R3		; адрес нечетный, компаратор
		mov	R3, @R2			; сравнивает все 16 разрядов
2$:		mov	R0, R4			; запись не будет обнаружена
		dec	R2			;
		mov	#010004, @R2		;
		dec	R4			; R4 должен быть равен 1
		beq	3$			; выполнена старая инструкция
		halt				;
						;
3$:		mov	#4$, R2			; записываем по четному адресу
		mov	#010104, R3		; код инструкции  mov R1, R4
		mov	R3, @R2			; запись будет обнаружена 
4$:		mov	R0, R4			; 
		mov	#010004, @R2		;
		cmp	#2, R4			; R4 должен быть равен 2
		beq	tst5			; выполнена новая инструкция
		halt				;
;_____________________________________________________________________________
;
; Тесты корректности генерации и НЕ генерации исключений при предвыборке команд
;
tst5:		mov	#memlim-4, R5		; тестирование предвыборки
						; неисполняемой команды
		mov	#1$, @#trap4		; обращаемся просто за данными
		mov	4(R5), R0		; должно произойти исключение
		halt				; по зависанию шины
						;
1$:		mov	#fail, @#trap4		; инструкция rts PC
		mov	cmd1, 2(R5)		; возврат, нет исключения
		jsr	PC, 2(R5)		; на предвыборке команд
						;
		mov	cmd2+0, 0(R5)		; двухсловная инструкция
		mov	#2$, 2(R5)		; mov #ret, PC
		jmp	(R5)			; нет исключения
		halt				; 
						;
2$:		mov	#3$, @#trap4		;
		mov	cmd3, 2(R5)		; "mov (R0)+, (R0)+"
		mov	#tebuf, R0		; гарантированное исполнение
		mov	#12345, 0(R0)		; команды перед исключением
		clr	2(0)			; по предвыборке
		jmp	2(R5)			;
						;
3$:		cmp	(SP)+, #memlim+2	; проверим адрес возврата
		bne	4$			; из исключения
		cmp	#tebuf+4, R0		;
		bne	4$			;
		cmp	#12345, -(R0)		;
		beq	5$			;
4$:		halt				;
						;
5$:		mov	#6$, @#trap4		;
		mov	cmd4, 2(R5)		; слово приемника в унарной
		mov	#tebuf, R0		; команде сразу вызывает
		jmp	2(R5)			; исключение
						;
6$:		mov	#7$, @#trap4		;
		mov	cmd5, 2(R5)		; слово приемника в бинарной
		jmp	2(R5)			; команде регистр-память
7$:		cmp	(SP)+, #memlim+2	; сразу вызывает исключение
		bne	4$			;
		   				;
		mov	#10$, @#trap4		;
		mov	#tebuf, R0		;
		mov	cmd6, 2(R5)		; слово приемника в бинарной
		jmp	2(R5)			; команде память-память
10$:		cmp	(SP)+, #memlim+2	; сначала обработка источниа
		bne	4$			; потом вызывает исключение
		cmp	#tebuf+2, R0		;
		bne	4$			;
						;
						;
		mov	#11$, @#trap4		;
		mov	cmd7, 2(R5)		; слово источника в бинарной
		jmp	2(R5)			; команде память-память
11$:		cmp	(SP)+, #memlim+2	; сразу вызывает исключение
		bne	4$			;
		cmp	#tebuf+2, R0		;
		bne	4$			;
						;
		mov	#12$, @#trap4		;
		mov	cmd8, 2(R5)		; слово приемника в бинарной
		jmp	2(R5)			; команде память-память
12$:		cmp	(SP)+, #memlim+2	; 3-словной
		bne	4$			; сразу вызывает исключение
						;
		jmp	allok			;
;_____________________________________________________________________________
;
tst6:		mov	#101010, R0		;
		mov	#121212, R2		;
		mov	#161616, SP		;
		mov	@PC, SP			;
		mov	#200, R2		;
		clr	R0			;
						;
		br	1$			;
		br	1$			;
						;
1$:		cmp	SP, #012702		; opcode mov
		bne	2$			;
		tst	R0			;
		bne	2$			;
		jmp	allok			;
						;
2$: 		halt				;
;_____________________________________________________________________________
;
tst7:	        tstb	@#tpb			;
		bpl	tst7			;
		movb	#'+, @#tps		;
1$:		tstb	@#tpb			;
		bpl	1$			;
						;
		clr	-(SP)			;
		clr	-(SP)			;
		clr	-(SP)			;
		clr	-(SP)			;
		mov	#4$, @#64		;
		mov	#340, @#66		;
		mov	#2$, @#10		;
		mov	#740, @#12		;
		mov	#100, @#tpb		;
		fadd	SP			;
		halt				;
						;
2$:		mtps	#0			;
		halt				;
						;
4$:		mov	(SP)+, R0		;
		mov	(SP)+, R1		;
		cmp	R1, #400		;
		bne	5$			;
		cmp	R0, #2$+4		;
		bne	5$			;
		mov	#0, @#tpb		;
		movb	#'@, @#tps		;
5$:		halt				;
;_____________________________________________________________________________
;
allok:		iot				;
		.word	$tstok			;
		halt				;
						;
$tstok:		.ascii	<15><12>		;
		.asciz	<12><15>"Test passed OK (PC)"
		.even				;
						;
cmd1:		rts	PC			;
cmd2:		mov	#0, PC			;
cmd3:		mov	(R0)+, (R0)+		;
cmd4:		clr	@#tebuf			;
cmd5:		mov	R0, @#tebuf		;
cmd6:		mov	(R0)+, tebuf		;
cmd7:		mov	tebuf, (R0)+		;
cmd8:		mov	@#tebuf+0, @#tebuf+2	;
fail:		halt				;
;_____________________________________________________________________________
;
; Точка обработки IOT -  печать сообщения
; Адрес строки размещается сразу за инструкцией iot
;
type:		mov	R0, -(SP)		; за инструкцией iot следует
		mov	@2(SP),	R0		; адрес выводимой строки
						;
1$:		movb	(R0)+, -(SP)		; получим символ строки
		bne	2$			; не ноль - выводим
		tst	(SP)+			; найден конец строки
		mov	(SP)+, R0		; извлечем символ из стека
		add	#2, @SP			; корректируем адес воврата
		rti				;
						;
2$:		jsr	PC, putch		;
		tst	(SP)+			; извлечем символ из стека
		br	1$			; продолжаем вывод строки
;_____________________________________________________________________________
;
; Посылка символа 2(SP) в терминал.

putch:		tstb	@#tpb			; проверим готовности терминала
		bpl	putch			; не готов - ждем дальше
		movb	2(SP), @#tps		; посылаем символ из стека
		rts	PC			;
;_____________________________________________________________________________
;
outhex:		mov	R1, -(SP)		;
		mov	R0, -(SP)		;
						;
		bic	#177760, R0		;
		movb	1$(R0), R1		;
		mov	(SP), R0		;
		asr	R0			;
		asr	R0			;
		asr	R0			;
		asr	R0			;
		bic	#177760, R0		;
		movb	1$(R0), R0		;
		swab	R0			;
		bis	R0, R1			;
		mov	R1, @#177714		;
						;
		mov	(SP), R0		;
		swab	R0			;
		bic	#177760, R0		;
		movb	1$(R0), R1		;
		movb	1(SP), R0		;
		asr	R0			;
		asr	R0			;
		asr	R0			;
		asr	R0			;
		bic	#177760, R0		;
		movb	1$(R0), R0		;
		swab	R0			;
		bis	R0, R1			;
		mov	R1, @#177715		;
						;
		mov	(SP)+, R0		;
		mov	(SP)+, R1		;
		rts	PC			;
						;
1$:		.byte	077, 006, 133, 117	;
		.byte	146, 155, 175, 007	;
		.byte	177, 157, 167, 174	;
		.byte	071, 136, 171, 161	;
						;
hang:		mov	(SP), R0		;
		jsr	PC, outhex		;
1$:		wait				;
		br	1$			;
;_____________________________________________________________________________
;
		.end				;
