/
wordcopy_burst.picoasm
76 lines (65 loc) · 2.37 KB
/
wordcopy_burst.picoasm
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
.include "picoasm_hal.h"
#define hir_base x1
#define burst_base x2
#define msb_set x3
#define mask_4_lsb x4
#define src x5
#define dst x6
#define num_elems x7
#define burst_end x8
#define single_end x9
#define stat_busy x10
#define tmp x11
/*Word Copy using burst mode*/
.text
.balign 4
.globl _start
/*Status register values*/
.equ STAT_START, 1
.equ STAT_BUSY, 3
.equ STAT_DONE, 0
_start:
/*Set up constants.*/
li hir_base, HIR_REGS_BASE_ADDR
li burst_base, BURST_REGS_BASE_ADDR
sw zero, BURST_OFFSET(burst_base) /*no src-to-dest alignment offset.*/
li msb_set, 0x80000000
li mask_4_lsb, 0xfffffff0 /*mask to clear 4 lsbs*/
li stat_busy, STAT_BUSY
wait_start:
lw tmp, HIR3(hir_base) /*HIR3: ctrl-status*/
beqz tmp, wait_start
sw stat_busy, HIR3(hir_base) /*set status to 'Busy'*/
lw src, HIR0(hir_base) /*HIR0: src pointer*/
lw dst, HIR1(hir_base) /*HIR1: dst pointer*/
lw num_elems, HIR2(hir_base) /*HIR2: num words*/
slli num_elems, num_elems, 2 /*Multiple by 4 to convert to byte address offset.*/
add single_end, num_elems, src /*Turn into single end pointer.*/
and burst_end, num_elems, mask_4_lsb /*Nearest lower burst boundary*/
add burst_end, burst_end, src /*Turn into burst end pointer.*/
bgeu src, burst_end, single_loop_start
or src, src, msb_set /*Set msb to engage burst mode*/
or dst, dst, msb_set /*Set msb to engage burst mode*/
or burst_end, burst_end, msb_set /*Set msb to engage burst mode*/
burst_loop:
/*Copy 4-word burst by 4-word burst*/
lw tmp, 0(src)
addi src, src, 16
sw tmp, 0(dst)
addi dst, dst, 16
bltu src, burst_end, burst_loop
xor src, src, msb_set /*Clear msb again to turn off burst mode.*/
xor dst, dst, msb_set /*Clear msb again to turn off burst mode.*/
/*Copy remaining words word-by-word until we get to the end pointer.*/
single_loop_start:
bgeu src, single_end, end
single_loop:
lw tmp, 0(src)
addi src, src, 4
sw tmp, 0(dst)
addi dst, dst, 4
bltu src, single_end, single_loop
end:
sw zero, BURST4(burst_base) /*Do one more write to a burst register to ensure last burst transaction completed.*/
sw zero, HIR3(hir_base) /*set to 'Done'*/
j wait_start