From 603f220d14cf1fa28df2004f7dba1c5217447bb5 Mon Sep 17 00:00:00 2001 From: Natt Akuma Date: Fri, 2 Feb 2024 16:31:42 +0700 Subject: [PATCH] Add IA-32 assembly for ESFM feedback calculation --- extern/ESFMu/esfm.c | 68 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/extern/ESFMu/esfm.c b/extern/ESFMu/esfm.c index c70d6f53f..bed04cdf9 100644 --- a/extern/ESFMu/esfm.c +++ b/extern/ESFMu/esfm.c @@ -1744,7 +1744,6 @@ ESFM_process_feedback(esfm_chip *chip) { int channel_idx; - // TODO: the tight 29-iteration loop can be vectorized across channels for (channel_idx = 0; channel_idx < 18; channel_idx++) { esfm_slot *slot = &chip->channels[channel_idx].slots[0]; @@ -1753,7 +1752,6 @@ ESFM_process_feedback(esfm_chip *chip) uint10 f_num; int32_t wave_out, wave_last; int32_t phase_feedback; - uint19 regressed_phase; uint32_t iter_counter; uint3 waveform; uint3 mod_in_shift; @@ -1844,6 +1842,72 @@ ESFM_process_feedback(esfm_chip *chip) [exprom] "m" (exprom) : "cc", "ax", "bx", "cx", "dx", "r8", "r9", "r10", "r11" ); +#elif defined(__GNUC__) && defined(__i386__) + asm ( + "movzbl %b[wave], %%eax \n\t" + "shll $11, %%eax \n\t" + "leal %[sinrom], %%edi \n\t" + "addl %%eax, %%edi \n\t" + "shlw $3, %[eg_out] \n\t" + "xorl %[out], %[out] \n\t" + "movl %[out], %[last] \n\t" + "movl $29, %[i] \n" + "1: \n\t" + // phase_feedback = (wave_out + wave_last) >> 2; + "movl %[out], %%eax \n\t" + "addl %[last], %%eax \n\t" + "sarl $2, %%eax \n\t" + "movl %%eax, %[p_fb] \n\t" + // wave_last = wave_out + "movl %[out], %[last] \n\t" + // phase = phase_feedback >> mod_in_shift; + "movb %[mod_in], %%cl \n\t" + "sarl %%cl, %%eax \n\t" + // phase += phase_acc >> 9; + "movl %[p_acc], %%ebx \n\t" + "shrl $9, %%ebx \n\t" + "addl %%ebx, %%eax \n\t" + // lookup = logsinrom[(waveform << 10) | (phase & 0x3ff)]; + "andl $0x3ff, %%eax \n\t" + "movzwl (%%edi, %%eax, 2), %%ebx \n\t" + "movl %%ebx, %%eax \n\t" + // level = (lookup & 0x1fff) + (envelope << 3); + "movl $0x1fff, %%ecx \n\t" + "andl %%ecx, %%eax \n\t" + "addw %[eg_out], %%ax \n\t" + // if (level > 0x1fff) level = 0x1fff; + "cmpl %%ecx, %%eax \n\t" + "cmoval %%ecx, %%eax \n\t" + // wave_out = exprom[level & 0xff] >> (level >> 8); + "movb %%ah, %%cl \n\t" + "movzbl %%al, %%eax \n\t" + "leal %[exprom], %[out] \n\t" + "movzwl (%[out], %%eax, 2), %[out] \n\t" + "shrl %%cl, %[out] \n\t" + // if (lookup & 0x8000) wave_out = -wave_out; + // in other words, lookup is negative + "movl %[out], %%ecx \n\t" + "negl %%ecx \n\t" + "testw %%bx, %%bx \n\t" + "cmovsl %%ecx, %[out] \n\t" + // phase_acc += phase_offset + "addl %[p_off], %[p_acc] \n\t" + // loop + "decl %[i] \n\t" + "jne 1b \n\t" + : [p_fb] "=&m" (phase_feedback), + [p_acc] "+r" (phase_acc), + [out] "=&r" (wave_out), + [last] "=&m" (wave_last), + [eg_out] "+m" (eg_output) + : [p_off] "m" (phase_offset), + [mod_in] "m" (mod_in_shift), + [wave] "m" (waveform), + [sinrom] "m" (logsinrom), + [exprom] "m" (exprom), + [i] "m" (iter_counter) + : "cc", "ax", "bx", "cx", "di" + ); #else wave_out = 0; wave_last = 0;