.global	main
.eqv	TMIN	8
.macro	.TABLE	%name
.data
%name:	.word	0	# адрес начала стека
	.word	0	# адрес вершины стека
	.word	0	# адрес границы стека
	.word	0	# нижняя граница
.text
	li	a0 TMIN
	li	a7 9
	ecall
	la	t0 %name
	sw	a0 (t0)
	sw	a0 4(t0)
	sw	a0 12(t0)
	addi	a0 a0 TMIN
	sw	a0 8(t0)
.end_macro
.text

# Заведение нового массива и копирование туда старого
.macro	scale	%cmd	# stack -> stack
	mv	t5 a0		# Описатель стека
	lw	t1 (t5)		# Старый массив
	lw	t2 4(t5)	# Вершина
	lw	t3 8(t5)	# Граница
	sub	t4 t3 t1	# Размер
	%cmd	t3 t4 1		# Новый размер (%cmd — либо srai, либо slli)
	mv	a0 t3
	li	a7 9		# Заказ памяти
	ecall
	sw	a0 (t5)		# Новый массив
	add	t6 a0 t3
	sw	t6 8(t5)	# Новая граница
	srai	t3 t3 2
	add	t6 a0 t3
	sw	t6 12(t5)	# Новая нижняя граница
	mv	t6 t1
copy:	bge	t1 t2 done	# Пока не достигли границы
	lw	t0 (t1)		# копируем массив
	sw	t0 (a0)
	addi	t1 t1 4
	addi	a0 a0 4
	j	copy
done:	sw	a0 4(t5)	# Новая вершина
	# TODO NOT IMPLEMENTED free t1
	mv	a0 t5		# восстановим a0
.end_macro
	
downscale:
	scale	srai
	ret
upscale:
	scale	slli
	ret
	
# Добавление element в стек stack
push:	# stack element -> stack
	addi	sp sp -8
	sw	ra -4(sp)
	sw	a1 (sp)
	
	lw	t1 4(a0)	# Вершина
	lw	t2 8(a0)	# Граница
	bltu	t1 t2 push_same	# Не надо масштабировать
	call	upscale		# Увеличиваем массив вдвое
	lw	a1 (sp)		# Восстанавливаем a1
	lw	t1 4(a0)	# Новая вершина
push_same:
	sw	a1 (t1)		# Положим a1 на стек
	addi	t1 t1 4
	sw	t1 4(a0)	# Обновим вершину
	lw	ra -4(sp)
	addi	sp sp 8
	ret

# Снятие элемента со стека stack
pop:	# stack -> element
	addi	sp sp -4
	sw	ra (sp)
	
	lw	t1 4(a0)	# Вершина
	lw	t2 12(a0)	# Нижняя граница
	bgeu	t1 t2 pop_same	# Не надо масштабировать
	lw	t3 8(a0)	# Граница
	lw	t0 (a0)		# Начало
	sub	t3 t3 t0	# Размер
	li	t0 TMIN
	ble	t3 t0 pop_same	# Не надо масштабировать
	call	downscale	# Уменьшаем массив вдвое
	lw	t1 4(a0)	# Новая вершина
pop_same:
	addi	t1 t1 -4
	lw	t0 (t1)		# Снимем значение
	sw	t1 4(a0)	# Обновим вершину
	mv	a0 t0

	lw	ra (sp)
	addi	sp sp 4
	ret
	
main:	.TABLE	stack
	li	s1 1
	li	s0 29
loop:	la	a0 stack
	mv	a1 s1
	call	push
	addi	s1 s1 1
	blt	s1 s0 loop

	li	s1 1
	li	s0 29
oloop:	la	a0 stack
	call	pop
	li	a7 1
	ecall
	li	a0 ' '
	li	a7 11
	ecall
	addi	s1 s1 1
	blt	s1 s0 oloop

	li	a7 10
	ecall
