I am writing Nios 2 code on an emulator, It takes the state of a button, if it is high, then looks at a couple of switches and get the number from the switch it is assigned to then puts that number into a seven segment display. This loops 4 times and is supposed to stop after it runs 4 times buyt it keeps resetting its counter after it runs 4 times.
this is set to run on an emulator called cpulator. the specific type is the de-10 lite https://cpulator.01xz.net/?sys=nios-de10-lite I need this block of code to run like a subroutine. call it once, have it gather the numbers, then exit and move on to the next instruction after it was called.
.macro push reg
subi sp, sp, 4
stw \reg, 0(sp)
.endm
.macro pop reg
ldw \reg, 0(sp)
addi sp, sp, 4
.endm
.equ IO_BASE, 0xff200000
.equ LED, 0x00
.equ SWITCH, 0x40
.equ BUTTON, 0x50
.equ IO_BASE, 0xff200000
.equ SEG1, 0x20
.equ SEG2, 0x30
.equ TOS, 0x04000000
.equ TIME, 0x2000
.equ TIME_CTRL, TIME+0x4
.equ TIME_START,TIME+0x8
.global _start
_start:
call _get_the_numbers
_stop: br _stop
_get_the_numbers:
movui r22, 0x0200
movi r19, 4
movi r18, 0
movi r17, 1
movia sp, TOS
movia r23, IO_BASE # device base address
check_button0:
ldwio r2, BUTTON(r23) # read buttons
andi r2, r2, 0b01 # bit mask for button0
bne r2, r0, pressed # branch if button0 down
br check_button0
#r3 pulled value from switches
#r4 moved value
#r5 the dividing number
#r6 the divided number
#r7 the counter
#r8 the loop ender value
pressed:
ldwio r2, SWITCH(r23) # once up read switches
stwio r2, LED(r23) # write to LEDs
ldwio r3, LED(r23)
mov r4, r3 # moves the exponed number into r3
movi r5, 2 # sets r5 as the dividing num
movi r8, 1
movi r7, 0 # sets the counter as the 0
beq r3, r0, wait_for_up
call _expon
beq r6, r5, wait_for_up # checks to see of the exponed number is now 0 and sends to
_expon:
div r6, r4, r5 #divides the exponed number by 2
addi r7, r7, 1 # adds 1 to the counter
mov r4, r6
beq r4, r8, wait_for_up
br _expon
wait_for_up:
ldwio r2, BUTTON(r23) # read buttons
andi r2, r2, 0b01 # bit mask for button0
bne r2, r0, numstuff # if down wait till up
seg7_output: # arg r2 number
push r2
push r3 #\
push r4 # \
push r5 # stack
push r6 # /
push r7 #/
stwio r0, SEG1(r23) # clear 7seg hex0
stwio r0, SEG2(r23) # clear 7seg hex1
bne r2, r0, seg7_not_zero # if number 0 send now no math
ldb r4, seg7_numbers(r0) # get 0's 7seg equivalent
stwio r4, SEG1(r23) # display
br _seg7_loop # skip most code below
seg7_not_zero:
movia r3, 1 # r3 divider
movia r6, 0 # r6 counter
seg7_max_digits:
div r4, r2, r3
beq r4, r0, _seg7_max_digits
muli r3, r3, 10
addi r6, r6, 1
br seg7_max_digits
_seg7_max_digits:
seg7_loop:
subi r6, r6, 1
movi r4, 10
div r3, r3, r4 # new divider
div r4, r2, r3 # divide
mov r7, r4 # keep copy of raw number in r7
ldb r5, seg7_numbers(r4) # get new 7-seg number
muli r4, r6, 8 # convert r6 to bytes
sll r5, r5, r4 # shift left
cmpgti r4, r4, 24 # should we use the left most 7-seg address?
bne r4, r0, seg7_use_seg2
ldwio r4, SEG1(r23) # get old 7-seg values
or r4, r4, r5 # combine old and new values
stwio r4, SEG1(r23) # display
br seg7_skip_seg2
seg7_use_seg2:
ldwio r4, SEG2(r23) # get old 7-seg values
or r4, r4, r5 # combine old and new values
stwio r4, SEG2(r23) # display
seg7_skip_seg2:
mul r7, r7, r3 # get next number
sub r2, r2, r7
cmpeqi r4, r3, 1 # loop until 1s position
beq r4, r0, seg7_loop
_seg7_loop:
pop r7 #\
pop r6 # \
pop r5 # unstack
pop r4 # /
pop r3 #/
pop r2
ret
start_timer: # arg: r2 timer start value
push r2 # stack
stwio r0, TIME(r23) # reset timer
sthio r2, TIME_START(r23) # low halfword of counter start value
srli r2, r2, 16 # shift to hi-bits
sthio r2, TIME_START+4(r23) # high halfword of counter start value
movi r2, 0b0100 # mask to start timer
sthio r2, TIME_CTRL(r23) # start the timer
pop r2 # unstack
ret
wait_for_timeout: # no args
push r2 # stack
wait_loop:
ldwio r2, TIME(r23) # read timer status
cmpeqi r2, r2, 0b10 # is it running ?
bne r2, r0, wait_loop # loop until timer expired
pop r2 # unstack
ret
numstuff:
#ldw r21, 0(r22) #pulls the previous number
#stw r7, 0(r22) # stores the number into the first word
muli r11, r12, 10 #multiplies the prev num by 10
mov r10, r7 #moves the word to r10 for math
add r12, r11, r10
mov r2, r12
mov r22, r12
call seg7_output
movia r2, 1000000000 # value for 5 second timer
call start_timer # start the timer
call wait_for_timeout # wait for it to timeout
add r18, r18, r17
bleu r18, r19, check_button0
.org 0x1000
.data
seg7_numbers: .byte 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x6f
# 0 1 2 3 4 5 6 7 8 9