.eqv	cell.next	0	# смещение до ссылки
.eqv	cell.data	4	# смещение до данных
.eqv	cell		8	# размер структуры (1 слово данных)

.data
list:	.align	2		# стартовый элемент списка
	.space	cell		# второе слово не используется
	
# Добавление %data после эелемента %cell
.macro	append	%cell %data
	mv	a0 %cell
	mv	a1 %data
	call 	list_append
.end_macro

# Поиск %value в списке %list
.macro	find	%list %value
	la	a0 %list
	li	a1 %value
	call	list_prev
	lw	a0 cell.next(a0)
.end_macro

# Вставка значения %value в упорядоченный список %list
.macro	insert %list %value
	la	a0 %list
	li	a1 %value
	call	list_gt
	call	list_append
.end_macro

# Удаление ячейки, стоящей после %cell
.macro	delete	%cell
	mv	a0 %cell
	call	list_delete
.end_macro

# Вывод регистра в нужном формате с разделителем
.macro	print	%reg %ecall %sep
	mv	a0 %reg
	li	a7 %ecall
	ecall
	li	a0 %sep
	li	a7 11
	ecall
.end_macro

# Вывод адреса и содержимого ячейки (или 0)
.macro	printl	%reg
	beqz	%reg null
	lw	a1 cell.data(%reg)
	print	%reg 34 ' '
	print	a1 1 '\n'
	j	fin
null:	print	%reg 1 '\n'
fin:
.end_macro

# Вывод всего списка %list
.macro	print_list %list
	la	a0 list
	call	list_print
.end_macro

.text
main:	li	s1 8
	la	s2 list
fill:	append	s2 s1		# Добавление в начало списка
	addi	s1 s1 -1
	bgtz	s1 fill
	print_list a0		# Должна получиться возрастающая последовательность
	find	list 5
	printl	a0
	find	list 4
	delete	a0		# Должен удалиться следующий элемент — 5
	la	a0 list
	delete	a0		# Должен удалиться первый элемент — 1
	print_list a0
	insert	list 5		# Должен вставиться после 4
	insert	list 5		# Должен вставиться после 5
	insert	list 42		# Должен вставиться в конец
	insert	list 1		# Должен вставиться в начало
	print_list a0
	find	list 11		# Нет такого
	printl	a0
	li	a7 10
	ecall

# Вывод всего списка list
list_print:	# list
	mv	t1 a0
lp_nxt:	lw	t1 cell.next(t1)
	beqz	t1 lp_end
	lw	t0 cell.data(t1)
	print	t0 1 ' '
	j	lp_nxt
lp_end:	li	a0 '\n'
	li	a7 11
	ecall
	ret

# Вставка после cell нового элемента со значением data
list_append:	# cell data
	mv	t2 a0
	lw	t1 cell.next(t2)	# ссылка на следующий элемент
	li	a0 cell			# заказ памяти под структуру
	li	a7 9
	ecall
	sw	t1 cell.next(a0)	# перекладывавем ссылку на следующий
	sw	a1 cell.data(a0)	# записываем данные
	sw	a0 cell.next(t2)	# подменяем ссылку на новый адрес
	ret

# Удаление из списка элемента, стоящего после cell
# Возвращается адрес этого элемента или 0, если cell — последний
list_delete:	# cell
	mv	t1 a0			# Предыдущий элемент
	lw	a0 cell.next(a0)	# Удаляемый элемент
	bnez	a0 ld_del		# (Если он есть)
	ret				# Если там 0, вернём 0
ld_del:	lw	t0 cell.next(a0)	# Элемент после удаляемого
	sw	t0 cell.next(t1)	# Переписываем ссылку на него
	# здесь должно быть освобождение двух слов памяти по адресу a0
	ret
	
# Поиск по условию value в списке list, возвращается предыдущий элемент
# или последний, если условие не выполняется
# Условие — инструкция сравнения+перехода двух регистров %branch
.macro	list_cond	%branch
proc:	# list value
	lw	t1 cell.next(a0)	# Следующий элемент списка
	beqz	t1 yes			# Список закончился, элемент не найден
	lw	t0 cell.data(t1)	# Значение для сравнения
	%branch	t0 a1 yes		# Найден ли элемент?
	mv	a0 t1			# Перейдём к следующему
	j	proc
yes:	ret
.end_macro
list_prev:	list_cond beq		# Поиск равного
list_gt:	list_cond bgt		# Поиск большего
