	.section	.text
	.global	atoi
	.type	atoi, %function
atoi:
	push	{r7, lr}
	sub	sp, sp, #48
	add	r7, sp, #0
	str	r0, [r7, #12]		@ Save string
	str	r1, [r7, #8]		@ Save remain
	str	r2, [r7, #4]		@ Save result
	str	r3, [r7]		@ Save base
	movs	r3, #1
	str	r3, [r7, #32]		@ any = 1
	movs	r3, #0
	str	r3, [r7, #28]		@ acc = 0
	mov	r3, #-1
	str	r3, [r7, #24]		@ cutoff = 4294967295
	ldr	r3, [r7]
	cmp	r3, #1			@ base < 2
	bls	invalid			@ Return error if no carry
	cmp	r3, #36			@ base > 36
	bls	skip_space_prepare	@ Proceed if no carry
invalid:
	mvn	r3, #21			@ -EINVAL
	b	end
skip_space_prepare:
	movs	r3, #1
	str	r3, [r7, #40]		@ i = 1
	b	skip_space
skip_space_next:
	ldr	r3, [r7, #40]
	adds	r3, r3, #1
	str	r3, [r7, #40]
skip_space:
	ldr	r2, [r7, #12]		@ Load string
	ldr	r3, [r7, #40]		@ Load i
	add	r3, r3, r2		@ r3 = string + i
	ldrb	r3, [r3]		@ r3 = *r3
	cmp	r3, #32			@ r3 == 32 (space)
	beq	skip_space_next		@ if true, proceed to next byte
	ldr	r0, [r7, #24]		@ Load cutoff
	ldr	r1, [r7]		@ Load base
	bl	div			@ XXX: expects a record
	str	r1, [r7, #20]		@ cutlim = remainder of cutoff divided by base
	ldr	r1, [r7]		@ Load base
	ldr	r0, [r7, #24]		@ Load cutoff
	bl	div			@ XXX: expects a record
	str	r0, [r7, #24]		@ cutoff = cutoff divided by base
	ldr	r2, [r7, #12]		@ Load string
	ldr	r3, [r7, #40]		@ Load i
	add	r3, r3, r2		@ r3 = string + i
	ldrb	r3, [r3]		@ r3 = *r3
	strb	r3, [r7, #47]		@ ch = r3
	b	convert
digit_test:
	ldrb	r3, [r7, #47]		@ Load ch
	cmp	r3, #47			@ ch >= 48 (zero)
	bls	capital_letter_test
	cmp	r3, #57			@ ch <= 57 (nine)
	bhi	capital_letter_test
	subs	r3, r3, #48
	strb	r3, [r7, #47]		@ ch = ch - 48
	b	is_ch_less_than_base
capital_letter_test:
	cmp	r3, #64
	bls	lowercase_letter_test	@ ch >= 64 (A)
	cmp	r3, #90
	bhi	lowercase_letter_test	@ ch <= 90 (Z)
	subs	r3, r3, #55
	strb	r3, [r7, #47]		@ ch = ch + 55
	b	is_ch_less_than_base
lowercase_letter_test:
	cmp	r3, #96
	bls	is_any_zero		@ ch >= 96 (a)
	cmp	r3, #122
	bhi	is_any_zero		@ ch <= 122 (z)
	subs	r3, r3, #87
	strb	r3, [r7, #47]		@ ch = ch + 87
is_ch_less_than_base:
	ldr	r2, [r7]		@ Load base
	cmp	r2, r3
	bls	is_any_zero		@ Nope!
	ldr	r3, [r7, #32]		@ Load any
	cmp	r3, #0			@ any == zero
	beq	assign_any_zero
	ldr	r2, [r7, #28]		@ Load acc
	ldr	r3, [r7, #24]		@ Load cutoff
	cmp	r2, r3			@ acc > cutoff
	bhi	assign_any_zero
	ldr	r2, [r7, #28]		@ Load acc
	ldr	r3, [r7, #24]		@ Load cutoff
	cmp	r2, r3			@ acc == cutoff
	bne	assign_any_one
	ldrb	r3, [r7, #47]		@ Load ch
	ldr	r2, [r7, #20]		@ Load cutlim
	cmp	r2, r3			@ ch > cutlim
	bcs	assign_any_one
assign_any_zero:
	movs	r3, #0
	str	r3, [r7, #32]		@ any = 0
	b	assign_ch
assign_any_one:
	movs	r3, #1
	str	r3, [r7, #32]		@ any = 1
	ldr	r3, [r7, #28]		@ Load acc
	ldr	r2, [r7]		@ Load base
	mul	r3, r2, r3
	str	r3, [r7, #28]		@ acc = acc * base
	ldrb	r3, [r7, #47]		@ Load ch
	ldr	r2, [r7, #28]		@ Load acc
	add	r3, r3, r2
	str	r3, [r7, #28]		@ acc = acc + ch
assign_ch:
	ldr	r3, [r7, #40]		@ Load i
	adds	r3, r3, #1
	str	r3, [r7, #40]		@ i = i + 1
	ldr	r2, [r7, #12]		@ Load string
	ldr	r3, [r7, #40]		@ Load i
	add	r3, r3, r2		@ r3 = string + i
	ldrb	r3, [r3]		@ r3 = *r3
	strb	r3, [r7, #47]		@ ch = r3
convert:
	ldr	r3, [r7, #12]		@ Load string
	ldrb	r3, [r3]		@ r3 = *r3
	mov	r2, r3
	ldr	r3, [r7, #40]		@ Load i
	cmp	r3, r2			@ i <= r3
	bls	digit_test
	b	is_any_zero
is_any_zero:
	ldr	r3, [r7, #32]
	cmp	r3, #0
	bne	is_not_remain_null	@ Nope!
	ldr	r3, [r7, #4]		@ Load result
	mov	r2, #-1
	str	r2, [r3]		@ *result = 4294967295
	mvn	r3, #33			@ Return -ERANGE
	b	end
is_not_remain_null:
	ldr	r3, [r7, #8]		@ Load remain
	cmp	r3, #0
	beq	assign_result		@ Nope!
	ldr	r3, [r7, #12]		@ Load string
	ldrb	r2, [r3]		@ r2 = *r3
	ldr	r3, [r7, #40]		@ Load i
	sub	r2, r2, r3		@ r2 = *string - i
	ldr	r3, [r7, #8]		@ Load remain
	strb	r2, [r3]		@ remain = r2
	movs	r3, #1
	str	r3, [r7, #36]		@ index2 = 1
	b	assign_remain
assign_remain_byte:
	ldr	r2, [r7, #12]		@ Load string
	ldr	r3, [r7, #40]		@ Load i
	add	r2, r2, r3		@ r2 = string + i
	ldr	r1, [r7, #8]		@ Load remain
	ldr	r3, [r7, #36]		@ Load index2
	add	r3, r3, r1		@ r3 = remain + index2
	ldrb	r2, [r2]		@ r2 = *r2
	strb	r2, [r3]		@ r3 = r2
	ldr	r3, [r7, #40]		@ Load i
	adds	r3, r3, #1
	str	r3, [r7, #40]		@ i = i + 1
	ldr	r3, [r7, #36]		@ Load index2
	adds	r3, r3, #1
	str	r3, [r7, #36]		@ index2 = index2 + 1
assign_remain:
	ldr	r3, [r7, #12]		@ Load string
	ldrb	r3, [r3]		@ r3 = *r3
	mov	r2, r3
	ldr	r3, [r7, #40]		@ Load i
	cmp	r3, r2			@ i <= r3
	bls	assign_remain_byte
assign_result:
	ldr	r3, [r7, #4]		@ Load result
	ldr	r2, [r7, #28]		@ Load acc
	str	r2, [r3]		@ *r3 = r2
	movs	r3, #0			@ Return zero
end:
	mov	r0, r3
	adds	r7, r7, #48
	mov	sp, r7
	pop	{r7, pc}
