-
Notifications
You must be signed in to change notification settings - Fork 3
/
blockcopy.h
104 lines (98 loc) · 2.92 KB
/
blockcopy.h
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
#ifndef _BLOCK_COPY_H
#define _BLOCK_COPY_H
#pragma GCC optimize ("-fomit-frame-pointer")
/**
* ata_read_long_movem
*
* Fast copy of a 512-byte sector using movem
* Adapted from the open source at_apollo_device by Frédéric REQUIN
* https://github.com/fredrequin/at_apollo_device
*
* NOTE!
* The 68000 does an extra memory access at the end of a movem instruction!
* Source: https://github.com/prb28/m68k-instructions-documentation/blob/master/instructions/movem.md
*
* With the src of end-52 the error reg will be harmlessly read instead.
*
* @param source Pointer to drive data port
* @param destination Pointer to source buffer
*/
static inline void ata_read_long_movem (void *source, void *destination) {
asm volatile (
"lea.l 460(%0),%0 \n\t"
"offset = 0 \n\t"
".rep 9 \n\t"
"movem.l (%0),d0-d7/a1-a4/a6 \n\t"
"movem.l d0-d7/a1-a4/a6,offset(%1) \n\t"
"offset = offset + 52 \n\t"
".endr \n\t"
"movem.l 8(%0),d0-d7/a1-a3 \n\t"
"movem.l d0-d7/a1-a3,offset(%1) \n\t"
:
:"a" (source),"a" (destination)
:"a1","a2","a3","a4","a6","d0","d1","d2","d3","d4","d5","d6","d7"
);
}
/**
* ata_write_long_movem
*
* Fast copy of a 512-byte sector using movem
* Adapted from the open source at_apollo_device by Frédéric REQUIN
* https://github.com/fredrequin/at_apollo_device
*
* @param source Pointer to source buffer
* @param destination Pointer to drive data port
*/
static inline void ata_write_long_movem (void *source, void *destination) {
asm volatile (
".rep 9 \n\t"
"movem.l (%0)+,d0-d7/a1-a4/a6 \n\t"
"movem.l d0-d7/a1-a4/a6,(%1) \n\t"
".endr \n\t"
"movem.l (%0)+,d0-d7/a1-a3 \n\t"
"movem.l d0-d7/a1-a3,(%1) \n\t"
:
:"a" (source),"a" (destination)
:"a1","a2","a3","a4","a6","d0","d1","d2","d3","d4","d5","d6","d7"
);
}
/**
* ata_read_long_move
*
* Read a sector using move - faster than movem on 68020+
*
*/
static inline void ata_read_long_move (void *source, void *destination) {
asm volatile (
"move.l #3,d0 \n\t"
".l1: \n\t"
".rept 32 \n\t"
"move.l (%0),(%1)+ \n\t"
".endr \n\t"
"dbra d0,.l1"
:
:"a" (source), "a" (destination)
:"d0"
);
}
/**
* ata_write_long_move
*
* Write a sector using move - faster than movem on 68020+
*
*/
static inline void ata_write_long_move (void *source, void *destination) {
asm volatile (
"moveq.l #3,d0 \n\t"
".l2: \n\t"
".rept 32 \n\t"
"move.l (%0)+,(%1) \n\t"
".endr \n\t"
"dbra d0,.l2"
:
:"a" (source), "a" (destination)
:"d0"
);
}
#pragma GCC reset_options
#endif