summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/snd_mix_arm.S
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/snd_mix_arm.S')
-rw-r--r--apps/plugins/sdl/progs/quake/snd_mix_arm.S129
1 files changed, 129 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/snd_mix_arm.S b/apps/plugins/sdl/progs/quake/snd_mix_arm.S
new file mode 100644
index 0000000000..15733d8912
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/snd_mix_arm.S
@@ -0,0 +1,129 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2019 Franklin Wei
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ***************************************************************************/
21
22 /** Sound mixing code for ARM. **/
23 /* Takes 8-bit mono audio and outputs stereo 16-bit samples.
24 * stereo volumes are passed as arguments.
25 *
26 * Bear with me. This is my first ARM assembly, ever.
27 */
28
29 .text
30 .align 2
31 .global SND_PaintChannelFrom8
32 .type SND_PaintChannelFrom8, %function
33
34#if defined(__ARM_ARCH_5TEJ__)
35SND_PaintChannelFrom8:
36 // r0: int true_lvol
37 // r1: int true_rvol
38 // r2: char *sfx
39 // r3: int count
40
41 stmfd sp!, {r4, r5, r6, r7, r8, sl}
42
43 ldr ip, =paintbuffer
44 ldr ip, [ip]
45
46 mov r0, r0, asl #16 // pre-scale both volumes by 2^16
47 mov r1, r1, asl #16
48
49 sub r3, r3, #1 // we'll count backwards
50 // sl = 0xffff0000
51 ldrh sl, =0xffff
52
53.loop:
54 ldrsb r4, [r2, r3] // load *sfx[i] -> r4
55
56 // keep endianness in mind here
57 // buffer looks like [left_0, left_1, right_0, right_1] in memory
58 // but it is loaded as [right1, right0, left1, left0] to registers
59 ldr r8, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
60
61 // handle high half (right channel) first
62 mul r5, r4, r1 // SCALEDRIGHT = SFXI * (true_rvol << 16) -- bottom half is zero
63
64 // r7 holds right channel in high half (dirty bottom half)
65 qadd r7, r5, r8 // RIGHTCHANORIG = SCALEDRIGHT + RIGHTCHANORIG (high half)
66
67 bic r7, r7, sl // zero bottom bits of r7
68
69 // trash r5, r6 and handle left channel
70 mul r5, r4, r0 // SCALEDLEFT = SFXI * (true_rvol << 16)
71
72 mov r8, r8, lsl #16 // extract original left channel from paintbuffer
73
74 // r8 holds left channel in high half with zero bottom half
75 qadd r8, r5, r8
76
77 // combine the two 16-bit samples in r7 as 32-bit [left:right]
78 // (use lsr to not sign-extend the lower half)
79 orr r7, r7, r8, lsr #16
80
81 str r7, [ip, r3, lsl #2] // write 32-bit to paintbuffer
82 subs r3, r3, #1
83 bgt .loop // must use instead of bne because of the corner case count=1
84
85
86
87 ldmfd sp!, {r4, r5, r6, r7, r8, sl}
88
89 bx lr
90
91#elif defined(__ARM_ARCH_6__) // ARMv6 with QADD16 (disabled)
92SND_PaintChannelFrom8:
93 // r0: int true_lvol
94 // r1: int true_rvol
95 // r2: char *sfx
96 // r3: int count
97
98 stmfd sp!, {r4, r5, r6, r7}
99
100 ldr ip, =paintbuffer
101 ldr ip, [ip]
102 sub r3, r3, #1 // we'll count backwards
103.loop:
104 ldrsb r4, [r2, r3] // load *sfx[i] -> r4
105
106 // keep endianness in mind here
107 // buffer looks like [left_0, left_1, right_0, right_1] in memory
108 // but it is loaded as [right1, right0, left1, left0] to registers
109 ldr r7, [ip, r3, lsl #2] // load paintbuffer[0:1] = RIGHTCHANNEL:LEFTCHANNEL
110
111 // handle high half (right channel) first
112 mul r5, r4, r1 // SCALEDRIGHT = SFXI * true_rvol
113 mul r6, r4, r0 // SCALEDLEFT = SFXI * true_rvol
114
115 orr r6, r6, r5, lsl #16
116
117 qadd16 r6, r6, r7
118
119 str r6, [ip, r3, lsl #2] // write 32-bit to paintbuffer
120
121 subs r3, r3, #1
122 bne .loop
123
124 ldmfd sp!, {r4, r5, r6, r7}
125
126 bx lr
127#else
128#error ARMv5/6 only
129#endif