Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
#
# lab3upg1main.s - version 2010-01-14
#
# Written by F Lundevall.
# Copyright abandoned.
# This file is in the public domain.
#

########################################
# Definitions of device-addresses
# and important constants.
#

# de2_pio_keys4 - 0x840
.equ  keys4_base,0x840

# uart_0 - 0x860
.equ    uart_0_base,0x860

# timer_1 - 0x920
.equ    timer_1_base,0x920

#
# Timer 1 time-out definition.
# The clock frequency at the lab session is 50 MHz.
# For simulation, use a 0.1-second time-out.
# At the lab session, use a 1-second time-out.
#
.equ    timer1count,5000000    # Change this value (and this comment!)

#
# End of definitions of device-addresses
# and important constants.
########################################


########################################
# Macro definitions begin here
#

#
# PUSH reg - push a single register on the stack
#
.macro PUSH reg
    subi sp,sp,4    # reserve space on stack
    stw  \reg,0(sp) # store register
.endm

#
# POP  reg - pop a single register from the stack
#
.macro POP  reg
    ldw  \reg,0(sp) # fetch top of stack contents
    addi sp,sp,4    # return previously reserved space
.endm

#
# PUSHMOST - push all caller-save registers plus ra
#
.set noat           # required since we push r1
.macro PUSHMOST
    PUSH  at        # push assembler-temporary register r1
    PUSH  r2
    PUSH  r3
    PUSH  r4
    PUSH  r5
    PUSH  r6
    PUSH  r7
    PUSH  r8
    PUSH  r9
    PUSH r10
    PUSH r11
    PUSH r12
    PUSH r13
    PUSH r14
    PUSH r15
    PUSH  ra        # push return address register r31
.endm

#
# POPMOST - pop ra plus all caller-save registers
# POPMOST is the reverse of PUSHMOST
#
# .set noat is already done above - no need to repeat that
.macro POPMOST
    POP   ra
    POP  r15
    POP  r14
    POP  r13
    POP  r12
    POP  r11
    POP  r10
    POP   r9
    POP   r8
    POP   r7
    POP   r6
    POP   r5
    POP   r4
    POP   r3
    POP   r2
    POP   at
.endm

#
# Macro definitions end here
########################################

.text
.align 2

########################################
# Stub - three machine instructions (remember,
# movia is expanded into two instructions).
# The stub program-code must be copied
# to the exception-address
# (0x800020 in the current system).
#
# Stub explanation:
# move address of exception handler
# into exception-temporary register et
# Use JMP to jump to the interrupt handler
# (whose address is now in et)
stub:
    movia   et,exchand
    jmp     et
#
# End of stub.
########################################


########################################
# The following section replaces the
# Altera-supplied initialization code.
#
.global alt_main
alt_main:
    nop
    wrctl   status,r0
    br      main
    
    nop
    nop
    # Those NOPs are really not necessary,
    # but may help when you debug the program.
    # Without the NOPs, the branch instruction
    # would just jump to the next address
    # sequentially, which can be confusing.

#
# End of replacement for Altera-supplied
# initialization code.
########################################

    
########################################
# Main program follows.
#

    .data
    .align 2
mytime: .word 0x5957

    .text
    .align 2

#
# The label main
# must be declared global
#
.global main

main:
  # Always disable interupts before
  # initializing any devices
    wrctl   status,r0
    
    #
    # Add your code here to copy the stub
    # to address 0x800020 and on.
    # Remember to copy all three instructions
    # (movia is expanded to two instructions).
    # 
    movia r8,stub # k�lla
    movia r9,0x800020 # destination
  ldw r10,0(r8) # l�s movia del 1
  stw r10,0(r9) # skriv
  ldw r10,4(r8) # l�s movia del 2
  stw r10,4(r9) # skriv
  ldw r10,8(r8) # l�s jump
  stw r10,8(r9) # skriv
          # initialisera annat
    #
    # Add your code here to initialize timer_1 for
    # continuous interrupts every 100 ms (0.1 s)
    #
    movia r8,0x920    # Sparar 0x920 i r8
    mov   r9,r0      # Ser till att det inte finns n�got skr�p i r9  
    movia  r9,49999999    # Sparar 5000 000 millisek i r9 
    stwio r9,8(r8)    # Sparar r9 i periodl 
    srai  r9,r9,16    # Skiftar v�rdet i r7 med 16 bitar och sparar i r7
    stwio r9,12(r8)    # sparar r9 i periodh
    mov  r9,r0      # Ser till att det inte finns n�got skr�p i r9
    movi r9,0b0111    # Sparar 0111 i r9. S�tter d� Continuous-Mode bit till 1 och interrupt on time out till 1
    stwio r9,4(r8)    # sparrar r9 i control
    
    mov  r8,r0
    movi r8,0x400 # bit 10 ettst�lld
  wrctl ienable,r8 # skriv CTL3
    
  
    

    #
    # For Assignment 4 (but not earlier!),
    # add code here to initialize de2_pio_keys4
    # for interrupts from KEY0
    #
  movia r8, 0x848     #store adress of the interrupt mask to the keys
  movia  r7, 0x0011  
  stwio r7, 0(r8)    #store the bits in the IO unit
  
  
  
    #
    # Add your code here to initialize the CPU for
    # interrupts from timer_1 (index 10) only.
    # For Assignment 4 (but not earlier!),
    # add code here to also initialize the CPU for
    # interrupts from de2_pio_keys4 (index 2)
    #
  movi  r7, 0x004
  rdctl r8, ienable
  or r7, r7, r8
  wrctl ienable, r7  #allow the device (keys) to interrupt shiet
  
  #enables interrupts in general
  movi r8,1
  wrctl status,r8 # skriv CTL0
    
    #
    # Add your code here to enable interrupts
    # by writing 1 to the status register
    #
  
    #
    # Set start value for prime-space exploration.
    movia    r4,471123
#
# Main loop starts here.
mainloop:
    call    primesearch
    PUSH r4
  movi r4,33
  trap
  POP r4
  mov r4,r2
     
#
# This is the end of the main loop.
# We jump back to the beginning.
  br mainloop


#
# End of main program.
########################################


########################################
# Exception handler.
#
# This exception handler is extremely simplified.
# You will expand and improve the handler.
# When you do this, you must add comments -
# and change this comment - to reflect your changes.
#
exchand:
    nop
    nop
    # Those NOPs are not really necessary.
    # However, in this particular program,
    # they may help you setting a breakpoint
    # at the beginning of the handler
    # when you debug the program.
    
    rdctl  et,estatus     # Stores estatus in the exception temporary register.
  andi   et,et,1       # Discard garbage bits
  beq    et,r0,noint     # If interrupts are globally disabled, then noint
  rdctl  et,ipending    # Stores the devices request status
  beq    et,r0,noint     # If no devices requested interrupts, then no interrupt.
  
  br      exc_was_interrupt # Det var ett avbrott hoppa till exc_was_interuppt
  
noint:

  PUSH r8          # Pushar r8 p� stacken f�r att vi inte ska br�ka med detta register
  movia r8,0x003b683a   # Flyttar 0x003b683a till r8. 0x003b683a �r maskinkod f�r trapp.
  ldw et,-4(ea)       # l�s instr n�rmast f�re returplats
  cmpeq et,et,r8       # j�mf�r trapp med et
  POP r8          # Popar r8
  bne et,r0,exc_was_trap  # om lika, hoppa till traphandler
  
    # Here we should check the contents of estatus
    # to see if interrupts were enabled (Condition 1).
    
    # Then we should check if ipending is nonzero
    # (Condition 2).

    # If Conditions 1 and 2 are both true, the cause of
    # exception must have been an interrupt. In this case,
    # we should jump to the interrupt-handling code. 
    
    # Now, we should check if the instruction at the
    # exception location is a TRAP instruction.
    
    # Then we should perhaps check if the bit-pattern,
    # at the exception location, is that of
    # an unimplemented instruction
    # that we handle by software emulation. However,
    # this would be beyond the scope of this course.
    
    # In this extremely simplified handler, we check nothing.

    # The following label is a place to jump to,
    # after making sure that the cause of exception
    # really was an interrupt.
exc_was_interrupt:

    # Since we had an interrupt, and not a TRAP,
    # we must subtract 4 from the contents of the
    # exception-address register (ea), so that
    # the interrupted instruction gets restarted
    # when we return from the interrupt.
    # This requirement is Nios2-specific.
    subi    ea,ea,4
    
  andi  et, et, 0x0004  # Keep the bit at index 2 in ienable (key device)
  bne   et, r0, keyint  # If that bit is zero, then the keys have not requested an interrupt, proceed.
  
  
    # This is the place to check if the interrupt
    # came from timer_1 or from another source.
    # Since we have only one source right now,
    # we omit the check (until Assignment 4).
    
    # The following code is specific for
    # interrupts from timer_1
timer1int:

    # Acknowledge the interrupt
    movia   et,timer_1_base
    PUSH    r8
    movi    r8,1
    stwio   r8,0(et)    # clears timeout bit
    POP     r8
    
    
  PUSH  ea        # Saves ea (exception return adress), so we may return properly
     rdctl  r24, ctl1    # Saves estatus to r24
    PUSH  r24        # saves estatus on the stack
    
    
    # This is a first, simple handler.
    # All we do when we get a timer interrupt
    # is print a T on the console.
    # Since the JTAG UART uses interrupts itself,
    # this program must be compiled with a special
    # system library using another UART for the console:
    # We use uart_0.

    # Before calling a subroutine, push r1 through r15, and r31.
    PUSHMOST

    
    movia   r4,mytime
    call    puttime
    movia   r4,mytime
    call    tick
    movi    r4,'T'
    
    trap
    
    POPMOST

    POP    r24      #restores estatus from the stack
    wrctl  ctl1, r24  #writes estatus to ctl1 (restore)
    POP    ea      #restores exception return adress 
    
    # Afterwards, restore saved register values.

    # Branch to the end of the exception handler.
    br      excend


keyint:
  PUSHMOST
  movia r8, 0x840      # Store the adress of the data register of the keys in r8
  stwio r0, 12(r8)    # ACKNOWLEDGE INTERRUPT
  ldwio r8, 0(r8)      # Read the contents of the data register
  
  andi  r5, r8, 0b0010  # Keep second bit (key1)
  bne r5, r0, key0
  PUSH r4
  movia r4, 'F'
  call out_char_uart_0
  movia r4, mytime
  stw   r0, 0(r4)
  POP r4
  
key0:andi  r8, r8, 1    # Discard all but the first bit
  beq   r8, r0, pressed  # If it is zero, then it is pressed
  
  movia r4, 'U'      # Else it is released, store U in r4
  call out_char_uart_0  # Print it
  POPMOST
  br excend        # Proceed
  
pressed: movia r4, 'D'      # This runs only if the button was pressed, store D in r4
  call out_char_uart_0  # Print it
  POPMOST
  br excend

    # The following label is a place to jump to,
    # after making sure that the cause of exception
    # really was the result of a trap instruction.
exc_was_trap:

    # Our trap handler will call a subroutine.
    # We save the return address register R31,
    # to avoid problems for the code containing
    # the trap instruction.
    PUSH    ra
    # Print character in R4 using out_char_uart_0.
    call    out_char_uart_0
    # Restore the saved register.
    POP     ra

    # Fall-through to the end of the handler.
    # No branch needed (right now at least).
    
    # This is the end of the exception handler.
excend:
    eret
    
#
########################################

########################################
# Helper functions and support code.
# You do not need to study the following code.
#

# out_char_uart_0 - send byte on uart0
# one parameter, in r4: byte to send
# no return value
#
  .global out_char_uart_0
out_char_uart_0:
    movia   r8,uart_0_base
    ldwio   r8,8(r8)        # get uart0 status
    andi    r8,r8,0x40      # check TxRDY bit
    beq     r8,r0,out_char_uart_0   # loop if not ready
    andi    r4,r4,0xff      # sanitize argument
    movia   r8,uart_0_base
    stwio   r4,4(r8)        # write to uart0 TX data
    ret

################################################################
#
# A simplified printf() replacement.
# Implements the following conversions: %c, %d, %s and %x.
# No format-width specifications are allowed,
# for example "%08x" is not implemented.
# Up to four arguments are accepted, i.e. the format string
# and three more. Any extra arguments are silently ignored.
#
# The printf() replacement relies on routines
# out_char_uart_0, out_hex_uart_0,
# out_number_uart_0 and out_string_uart_0
# in file oslab_lowlevel_c.c
#
# We need the macros PUSH and POP (defined previously).
#

.text
.global nios2int_printf
nios2int_printf:
    PUSH    ra    # PUSH return address register r31.
    PUSH    r16     # R16 will point into format string.
    PUSH    r17     # R17 will contain the argument number.
    PUSH    r18     # R18 will contain a copy of r5.
    PUSH    r19     # R19 will contain a copy of r6.
    PUSH    r20     # R20 will contain a copy of r7.
    mov     r16,r4  # Get format string argument
    movi    r17,0   # Clear argument number.
    mov     r18,r5  # Copy r5 to safe place.
    mov     r19,r6  # Copy r6 to safe place.
    mov     r20,r7  # Copy r7 to safe place.
asm_printf_loop:
    ldb     r4,0(r16)   # Get a byte of format string.
    addi    r16,r16,1   # Point to next byte
    # End of format string is marked by a zero-byte.
    beq     r4,r0,asm_printf_end
    cmpeqi  r9,r4,92    # Check for backslash escape.
    bne     r9,r0,asm_printf_backslash
    cmpeqi  r9,r4,'%'   # Check for percent-sign escape.
    bne     r9,r0,asm_printf_percentsign
asm_printf_doprint:
    # No escapes present, just print the character.
    movia   r8,out_char_uart_0
    callr   r8
    br      asm_printf_loop
asm_printf_backslash:
    # Preload address to out_char_uart_0 into r8.
    movia   r8,out_char_uart_0
    ldb     r4,0(r16)  # Get byte after backslash
    addi    r16,r16,1   # Increase byte count.
    # Having a backslash at the end of the format string
    # is illegal, but must not crash our printf code.
    beq     r4,r0,asm_printf_end
    cmpeqi  r9,r4,'n'   # Newline
    beq     r9,r0,asm_printf_backslash_not_newline
    movi    r4,10       # Newline
    callr   r8
    br      asm_printf_loop
asm_printf_backslash_not_newline:
    cmpeqi  r9,r4,'r'   # Return
    beq     r9,r0,asm_printf_backslash_not_return
    movi    r4,13       # Return
    callr   r8
    br      asm_printf_loop
asm_printf_backslash_not_return:
    # Unknown character after backslash - ignore.
    br      asm_printf_loop
asm_printf_percentsign:
    addi    r17,r17,1  # Increase argument count.
    cmpgei  r8,r17,4    # Check against maximum argument count.
    # If maximum argument count exceeded, print format string.
    bne     r8,r0,asm_printf_doprint
    cmpeqi  r9,r17,1    # Is argument number equal to 1?
    beq     r9,r0,asm_printf_not_r5  # beq jumps if cmpeqi false
    mov     r4,r18      # If yes, get argument from saved copy of r5.
    br      asm_printf_do_conversion
asm_printf_not_r5:
    cmpeqi  r9,r17,2    # Is argument number equal to 2?
    beq     r9,r0,asm_printf_not_r6  # beq jumps if cmpeqi false
    mov     r4,r19      # If yes, get argument from saved copy of r6.
    br      asm_printf_do_conversion
asm_printf_not_r6:
    cmpeqi  r9,r17,3    # Is argument number equal to 3?
    beq     r9,r0,asm_printf_not_r7  # beq jumps if cmpeqi false
    mov     r4,r20       # If yes, get argument from saved copy of r7.
    br      asm_printf_do_conversion
asm_printf_not_r7:
    # This should not be possible.
    # If this strange error happens, print format string.
    br      asm_printf_doprint
asm_printf_do_conversion:
    ldb     r8,0(r16)  # Get byte after percent-sign.
    addi    r16,r16,1   # Increase byte count.
    cmpeqi  r9,r8,'x'   # Check for %x (hexadecimal).
    beq     r9,r0,asm_printf_not_x
    movia   r8,out_hex_uart_0
    callr   r8
    br      asm_printf_loop
asm_printf_not_x:
    cmpeqi  r9,r8,'d'   # Check for %d (decimal).
    beq     r9,r0,asm_printf_not_d
    movia   r8,out_number_uart_0
    callr   r8
    br      asm_printf_loop
asm_printf_not_d:
    cmpeqi  r9,r8,'c'   # Check for %c (character).
    beq     r9,r0,asm_printf_not_c
    # Print character argument.
    br      asm_printf_doprint
asm_printf_not_c:
    cmpeqi  r9,r8,'s'   # Check for %s (string).
    beq     r9,r0,asm_printf_not_s
    movia   r8,out_string_uart_0
    callr   r8
    br      asm_printf_loop
asm_printf_not_s:
asm_printf_unknown:
    # We do not know what to do with other formats.
    # Print the format string text.
    movi    r4,'%'
    movia   r8,out_char_uart_0
    callr   r8
    ldb     r4,-1(r16)
    br      asm_printf_doprint
asm_printf_end:
    POP     r20
    POP     r19
    POP     r18
    POP     r17
    POP     r16
    POP     ra
    ret

#
# End of simplified printf() replacement code.
#
################################################################

#
# End of file.
#
.end