The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.

Dependencies:   GR-PEACH_video R_BSP TLV320_RBSP USBHost_custom

Fork of GR-PEACH_Audio_Playback_Sample by Renesas

Note

For a sample program of without LCD Board, please refer to GR-PEACH_Audio_Playback_Sample.

Introduction

The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.

1. Overview of the Sample Code

1.1 Software Block Diagram

Figure 1.1 shows the software block diagram.

/media/uploads/1050186/lcd_figure1_1.png

1.2 Pin Definitions

Table 1.1 shows the pins used in this sample code.

/media/uploads/1050186/lcd_table1_1.png

2. Sample Code Operating Environment

In order to operate this sample code, GR-PEACH, Audio Camera Shield and 7.1 inch LCD Shield must be needed. For details on Audio Camera Shield and 7.1 inch LCD Shield, please refer to the following links, respectively:

In this section, it is described that how board is configured and to control audio playback via command line and touch screen.

2.1 Operating Environment

Figure 2.1 shows the overview of the operating environment for this sample code.

/media/uploads/1050186/lcd_figure2_1.png

Figure 2.2 and 2.3 show how to configure GR-PEACH, Audio Camera Shield and 7.1 inch LCD shield when using USB0 and USB1, respectively.

/media/uploads/1050186/lcd_figure2_2.png /media/uploads/1050186/lcd_figure2_3.png

Table 2.1 lists the overview of Graphical User Interface (GUI) of this sample code.

/media/uploads/1050186/lcd_table2_1.png

2.2 List of User Operations

Table 2.2 shows the relationship among Audio Playback, Command Line and Onboard Switch.

/media/uploads/1050186/lcd_table2_2.png

3. Function Outline

Table 3.1, 3.2 and 3.3 shows the overview of functions implemented in this sample code.

/media/uploads/1050186/lcd_table3_1.png /media/uploads/1050186/lcd_table3_2.png /media/uploads/1050186/lcd_table3_3.png /media/uploads/1050186/lcd_figure3_1.png

3.1 Playback Control

This sample program supports the operation "play", "pause", "stop", "play next song" and "play previous song".

3.2 Trick Play Control

In order to enable/disable Repeat Mode, user need to type "repeat" on command line or click the corresponding icon shown in Table 2.2. By derault, Repeat Mode is enabled. When Repeat Mode is enabled, the first song is played back after the playback of the last song is finished. Otherwise, the playback is shopped when finishing to play back the last song.

3.3 How to see Song Information

The information of the song being played back can be seen by typing playinfo on command line. Table 3.4 lists the items user can see on the terminal.

/media/uploads/dkato/audioplayback_table3_4.png

3.4 How to analyze the folder structure in USB stick

In this sample code, the folder structure in USB stick is analyzed in the breadth-first order. Table 3.5 shows how the files in USB stick are numbered.

/media/uploads/dkato/audioplayback_table3_5.png

4.Others

4.1 Serial Communication Setting

With respect to the default serial communication related setting on mbed, please refer to the follwing link:
https://developer.mbed.org/teams/Renesas/wiki/GR-PEACH-Getting-Started#install-the-usb-serial-communication
Please set up the terminal software you would like to use on your PC in consideration of the above. For example, 9600 should be specified for the baud rate on the terminal in order to control this sample via command line.

4.2 Necessary modification when using GCC ARM Embedded

If you would like to use GCC ARM Embedded, you must revise the following linker script incorporated in mbed OS 5 package as follows:

  • Linker Script to be modified
    $(PROJECT_ROOT)/mbed-os/targets/TARGET_RENESAS/TARGET_RZ_A1H/device/TOOLCHAIN_GCC_ARM/RZA1H.ld

    Please note that $(PROJECT_ROOT) in the above denotes the root directory of this sample code

  • Before Modification

RZA1H.ld

/* Linker script for mbed RZ_A1H */

/* Linker script to configure memory regions. */
MEMORY
{
  ROM   (rx)  : ORIGIN = 0x00000000, LENGTH = 0x02000000
  BOOT_LOADER (rx) : ORIGIN = 0x18000000, LENGTH = 0x00004000 
  SFLASH (rx) : ORIGIN = 0x18004000, LENGTH = 0x07FFC000 
  L_TTB (rw)  : ORIGIN = 0x20000000, LENGTH = 0x00004000 
  RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 0x00700000
  RAM_NC (rwx) : ORIGIN = 0x20900000, LENGTH = 0x00100000
}
(snip)
  • After Modification

RZA1H.ld

/* Linker script for mbed RZ_A1H */

/* Linker script to configure memory regions. */
MEMORY
{
  ROM   (rx)  : ORIGIN = 0x00000000, LENGTH = 0x02000000
  BOOT_LOADER (rx) : ORIGIN = 0x18000000, LENGTH = 0x00004000 
  SFLASH (rx) : ORIGIN = 0x18004000, LENGTH = 0x07FFC000 
  L_TTB (rw)  : ORIGIN = 0x20000000, LENGTH = 0x00004000 
  RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 0x00180000
  RAM_NC (rwx) : ORIGIN = 0x20200000, LENGTH = 0x00680000
}
(snip)
Committer:
dkato
Date:
Fri Oct 16 04:28:07 2015 +0000
Revision:
0:ee40da884cfc
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:ee40da884cfc 1 /* libFLAC - Free Lossless Audio Codec library
dkato 0:ee40da884cfc 2 * Copyright (C) 2001-2009 Josh Coalson
dkato 0:ee40da884cfc 3 * Copyright (C) 2011-2014 Xiph.Org Foundation
dkato 0:ee40da884cfc 4 *
dkato 0:ee40da884cfc 5 * Redistribution and use in source and binary forms, with or without
dkato 0:ee40da884cfc 6 * modification, are permitted provided that the following conditions
dkato 0:ee40da884cfc 7 * are met:
dkato 0:ee40da884cfc 8 *
dkato 0:ee40da884cfc 9 * - Redistributions of source code must retain the above copyright
dkato 0:ee40da884cfc 10 * notice, this list of conditions and the following disclaimer.
dkato 0:ee40da884cfc 11 *
dkato 0:ee40da884cfc 12 * - Redistributions in binary form must reproduce the above copyright
dkato 0:ee40da884cfc 13 * notice, this list of conditions and the following disclaimer in the
dkato 0:ee40da884cfc 14 * documentation and/or other materials provided with the distribution.
dkato 0:ee40da884cfc 15 *
dkato 0:ee40da884cfc 16 * - Neither the name of the Xiph.org Foundation nor the names of its
dkato 0:ee40da884cfc 17 * contributors may be used to endorse or promote products derived from
dkato 0:ee40da884cfc 18 * this software without specific prior written permission.
dkato 0:ee40da884cfc 19 *
dkato 0:ee40da884cfc 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
dkato 0:ee40da884cfc 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
dkato 0:ee40da884cfc 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
dkato 0:ee40da884cfc 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
dkato 0:ee40da884cfc 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
dkato 0:ee40da884cfc 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
dkato 0:ee40da884cfc 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
dkato 0:ee40da884cfc 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
dkato 0:ee40da884cfc 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
dkato 0:ee40da884cfc 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
dkato 0:ee40da884cfc 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dkato 0:ee40da884cfc 31 */
dkato 0:ee40da884cfc 32
dkato 0:ee40da884cfc 33 #ifdef HAVE_CONFIG_H
dkato 0:ee40da884cfc 34 # include <config.h>
dkato 0:ee40da884cfc 35 #endif
dkato 0:ee40da884cfc 36
dkato 0:ee40da884cfc 37 #include "private/cpu.h"
dkato 0:ee40da884cfc 38 #include <stdlib.h>
dkato 0:ee40da884cfc 39 #include <memory.h>
dkato 0:ee40da884cfc 40 #ifdef DEBUG
dkato 0:ee40da884cfc 41 # include <stdio.h>
dkato 0:ee40da884cfc 42 #endif
dkato 0:ee40da884cfc 43
dkato 0:ee40da884cfc 44 #if defined FLAC__CPU_IA32
dkato 0:ee40da884cfc 45 # include <signal.h>
dkato 0:ee40da884cfc 46
dkato 0:ee40da884cfc 47 static void disable_sse(FLAC__CPUInfo *info)
dkato 0:ee40da884cfc 48 {
dkato 0:ee40da884cfc 49 info->ia32.sse = false;
dkato 0:ee40da884cfc 50 info->ia32.sse2 = false;
dkato 0:ee40da884cfc 51 info->ia32.sse3 = false;
dkato 0:ee40da884cfc 52 info->ia32.ssse3 = false;
dkato 0:ee40da884cfc 53 info->ia32.sse41 = false;
dkato 0:ee40da884cfc 54 info->ia32.sse42 = false;
dkato 0:ee40da884cfc 55 }
dkato 0:ee40da884cfc 56
dkato 0:ee40da884cfc 57 static void disable_avx(FLAC__CPUInfo *info)
dkato 0:ee40da884cfc 58 {
dkato 0:ee40da884cfc 59 info->ia32.avx = false;
dkato 0:ee40da884cfc 60 info->ia32.avx2 = false;
dkato 0:ee40da884cfc 61 info->ia32.fma = false;
dkato 0:ee40da884cfc 62 }
dkato 0:ee40da884cfc 63
dkato 0:ee40da884cfc 64 #elif defined FLAC__CPU_X86_64
dkato 0:ee40da884cfc 65
dkato 0:ee40da884cfc 66 static void disable_avx(FLAC__CPUInfo *info)
dkato 0:ee40da884cfc 67 {
dkato 0:ee40da884cfc 68 info->x86.avx = false;
dkato 0:ee40da884cfc 69 info->x86.avx2 = false;
dkato 0:ee40da884cfc 70 info->x86.fma = false;
dkato 0:ee40da884cfc 71 }
dkato 0:ee40da884cfc 72 #endif
dkato 0:ee40da884cfc 73
dkato 0:ee40da884cfc 74 #if defined (__NetBSD__) || defined(__OpenBSD__)
dkato 0:ee40da884cfc 75 #include <sys/param.h>
dkato 0:ee40da884cfc 76 #include <sys/sysctl.h>
dkato 0:ee40da884cfc 77 #include <machine/cpu.h>
dkato 0:ee40da884cfc 78 #endif
dkato 0:ee40da884cfc 79
dkato 0:ee40da884cfc 80 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
dkato 0:ee40da884cfc 81 #include <sys/types.h>
dkato 0:ee40da884cfc 82 #include <sys/sysctl.h>
dkato 0:ee40da884cfc 83 #endif
dkato 0:ee40da884cfc 84
dkato 0:ee40da884cfc 85 #if defined(__APPLE__)
dkato 0:ee40da884cfc 86 /* how to get sysctlbyname()? */
dkato 0:ee40da884cfc 87 #endif
dkato 0:ee40da884cfc 88
dkato 0:ee40da884cfc 89 #ifdef FLAC__CPU_IA32
dkato 0:ee40da884cfc 90 /* these are flags in EDX of CPUID AX=00000001 */
dkato 0:ee40da884cfc 91 static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000;
dkato 0:ee40da884cfc 92 static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000;
dkato 0:ee40da884cfc 93 static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000;
dkato 0:ee40da884cfc 94 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000;
dkato 0:ee40da884cfc 95 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000;
dkato 0:ee40da884cfc 96 #endif
dkato 0:ee40da884cfc 97
dkato 0:ee40da884cfc 98 /* these are flags in ECX of CPUID AX=00000001 */
dkato 0:ee40da884cfc 99 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001;
dkato 0:ee40da884cfc 100 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200;
dkato 0:ee40da884cfc 101 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE41 = 0x00080000;
dkato 0:ee40da884cfc 102 static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE42 = 0x00100000;
dkato 0:ee40da884cfc 103
dkato 0:ee40da884cfc 104 #if defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 105 /* these are flags in ECX of CPUID AX=00000001 */
dkato 0:ee40da884cfc 106 static const unsigned FLAC__CPUINFO_IA32_CPUID_OSXSAVE = 0x08000000;
dkato 0:ee40da884cfc 107 static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX = 0x10000000;
dkato 0:ee40da884cfc 108 static const unsigned FLAC__CPUINFO_IA32_CPUID_FMA = 0x00001000;
dkato 0:ee40da884cfc 109 /* these are flags in EBX of CPUID AX=00000007 */
dkato 0:ee40da884cfc 110 static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX2 = 0x00000020;
dkato 0:ee40da884cfc 111 #endif
dkato 0:ee40da884cfc 112
dkato 0:ee40da884cfc 113 /*
dkato 0:ee40da884cfc 114 * Extra stuff needed for detection of OS support for SSE on IA-32
dkato 0:ee40da884cfc 115 */
dkato 0:ee40da884cfc 116 #if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN) && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS
dkato 0:ee40da884cfc 117 # if defined(__linux__)
dkato 0:ee40da884cfc 118 /*
dkato 0:ee40da884cfc 119 * If the OS doesn't support SSE, we will get here with a SIGILL. We
dkato 0:ee40da884cfc 120 * modify the return address to jump over the offending SSE instruction
dkato 0:ee40da884cfc 121 * and also the operation following it that indicates the instruction
dkato 0:ee40da884cfc 122 * executed successfully. In this way we use no global variables and
dkato 0:ee40da884cfc 123 * stay thread-safe.
dkato 0:ee40da884cfc 124 *
dkato 0:ee40da884cfc 125 * 3 + 3 + 6:
dkato 0:ee40da884cfc 126 * 3 bytes for "xorps xmm0,xmm0"
dkato 0:ee40da884cfc 127 * 3 bytes for estimate of how long the follwing "inc var" instruction is
dkato 0:ee40da884cfc 128 * 6 bytes extra in case our estimate is wrong
dkato 0:ee40da884cfc 129 * 12 bytes puts us in the NOP "landing zone"
dkato 0:ee40da884cfc 130 */
dkato 0:ee40da884cfc 131 # include <sys/ucontext.h>
dkato 0:ee40da884cfc 132 static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc)
dkato 0:ee40da884cfc 133 {
dkato 0:ee40da884cfc 134 (void)signal, (void)si;
dkato 0:ee40da884cfc 135 ((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6;
dkato 0:ee40da884cfc 136 }
dkato 0:ee40da884cfc 137 # elif defined(_MSC_VER)
dkato 0:ee40da884cfc 138 # include <windows.h>
dkato 0:ee40da884cfc 139 # endif
dkato 0:ee40da884cfc 140 #endif
dkato 0:ee40da884cfc 141
dkato 0:ee40da884cfc 142
dkato 0:ee40da884cfc 143 void FLAC__cpu_info(FLAC__CPUInfo *info)
dkato 0:ee40da884cfc 144 {
dkato 0:ee40da884cfc 145 /*
dkato 0:ee40da884cfc 146 * IA32-specific
dkato 0:ee40da884cfc 147 */
dkato 0:ee40da884cfc 148 #ifdef FLAC__CPU_IA32
dkato 0:ee40da884cfc 149 FLAC__bool ia32_fxsr = false;
dkato 0:ee40da884cfc 150 FLAC__bool ia32_osxsave = false;
dkato 0:ee40da884cfc 151 (void) ia32_fxsr; (void) ia32_osxsave; /* to avoid warnings about unused variables */
dkato 0:ee40da884cfc 152 memset(info, 0, sizeof(*info));
dkato 0:ee40da884cfc 153 info->type = FLAC__CPUINFO_TYPE_IA32;
dkato 0:ee40da884cfc 154 #if !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN)
dkato 0:ee40da884cfc 155 info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */
dkato 0:ee40da884cfc 156 #ifdef FLAC__HAS_X86INTRIN
dkato 0:ee40da884cfc 157 if(!FLAC__cpu_have_cpuid_x86())
dkato 0:ee40da884cfc 158 return;
dkato 0:ee40da884cfc 159 #else
dkato 0:ee40da884cfc 160 if(!FLAC__cpu_have_cpuid_asm_ia32())
dkato 0:ee40da884cfc 161 return;
dkato 0:ee40da884cfc 162 #endif
dkato 0:ee40da884cfc 163 {
dkato 0:ee40da884cfc 164 /* http://www.sandpile.org/x86/cpuid.htm */
dkato 0:ee40da884cfc 165 #ifdef FLAC__HAS_X86INTRIN
dkato 0:ee40da884cfc 166 FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
dkato 0:ee40da884cfc 167 FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
dkato 0:ee40da884cfc 168 #else
dkato 0:ee40da884cfc 169 FLAC__uint32 flags_ecx, flags_edx;
dkato 0:ee40da884cfc 170 FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx);
dkato 0:ee40da884cfc 171 #endif
dkato 0:ee40da884cfc 172 info->ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false;
dkato 0:ee40da884cfc 173 info->ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false;
dkato 0:ee40da884cfc 174 ia32_fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false;
dkato 0:ee40da884cfc 175 info->ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false;
dkato 0:ee40da884cfc 176 info->ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false;
dkato 0:ee40da884cfc 177 info->ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
dkato 0:ee40da884cfc 178 info->ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
dkato 0:ee40da884cfc 179 info->ia32.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
dkato 0:ee40da884cfc 180 info->ia32.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
dkato 0:ee40da884cfc 181 #if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 182 ia32_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
dkato 0:ee40da884cfc 183 info->ia32.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false;
dkato 0:ee40da884cfc 184 info->ia32.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false;
dkato 0:ee40da884cfc 185 FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
dkato 0:ee40da884cfc 186 info->ia32.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false;
dkato 0:ee40da884cfc 187 #endif
dkato 0:ee40da884cfc 188 }
dkato 0:ee40da884cfc 189
dkato 0:ee40da884cfc 190 #ifdef DEBUG
dkato 0:ee40da884cfc 191 fprintf(stderr, "CPU info (IA-32):\n");
dkato 0:ee40da884cfc 192 fprintf(stderr, " CMOV ....... %c\n", info->ia32.cmov ? 'Y' : 'n');
dkato 0:ee40da884cfc 193 fprintf(stderr, " MMX ........ %c\n", info->ia32.mmx ? 'Y' : 'n');
dkato 0:ee40da884cfc 194 fprintf(stderr, " SSE ........ %c\n", info->ia32.sse ? 'Y' : 'n');
dkato 0:ee40da884cfc 195 fprintf(stderr, " SSE2 ....... %c\n", info->ia32.sse2 ? 'Y' : 'n');
dkato 0:ee40da884cfc 196 fprintf(stderr, " SSE3 ....... %c\n", info->ia32.sse3 ? 'Y' : 'n');
dkato 0:ee40da884cfc 197 fprintf(stderr, " SSSE3 ...... %c\n", info->ia32.ssse3 ? 'Y' : 'n');
dkato 0:ee40da884cfc 198 fprintf(stderr, " SSE41 ...... %c\n", info->ia32.sse41 ? 'Y' : 'n');
dkato 0:ee40da884cfc 199 fprintf(stderr, " SSE42 ...... %c\n", info->ia32.sse42 ? 'Y' : 'n');
dkato 0:ee40da884cfc 200 # if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 201 fprintf(stderr, " AVX ........ %c\n", info->ia32.avx ? 'Y' : 'n');
dkato 0:ee40da884cfc 202 fprintf(stderr, " FMA ........ %c\n", info->ia32.fma ? 'Y' : 'n');
dkato 0:ee40da884cfc 203 fprintf(stderr, " AVX2 ....... %c\n", info->ia32.avx2 ? 'Y' : 'n');
dkato 0:ee40da884cfc 204 # endif
dkato 0:ee40da884cfc 205 #endif
dkato 0:ee40da884cfc 206
dkato 0:ee40da884cfc 207 /*
dkato 0:ee40da884cfc 208 * now have to check for OS support of SSE instructions
dkato 0:ee40da884cfc 209 */
dkato 0:ee40da884cfc 210 if(info->ia32.sse) {
dkato 0:ee40da884cfc 211 #if defined FLAC__NO_SSE_OS
dkato 0:ee40da884cfc 212 /* assume user knows better than us; turn it off */
dkato 0:ee40da884cfc 213 disable_sse(info);
dkato 0:ee40da884cfc 214 #elif defined FLAC__SSE_OS
dkato 0:ee40da884cfc 215 /* assume user knows better than us; leave as detected above */
dkato 0:ee40da884cfc 216 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__)
dkato 0:ee40da884cfc 217 int sse = 0;
dkato 0:ee40da884cfc 218 size_t len;
dkato 0:ee40da884cfc 219 /* at least one of these must work: */
dkato 0:ee40da884cfc 220 len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse);
dkato 0:ee40da884cfc 221 len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */
dkato 0:ee40da884cfc 222 if(!sse)
dkato 0:ee40da884cfc 223 disable_sse(info);
dkato 0:ee40da884cfc 224 #elif defined(__NetBSD__) || defined (__OpenBSD__)
dkato 0:ee40da884cfc 225 # if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__)
dkato 0:ee40da884cfc 226 int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE };
dkato 0:ee40da884cfc 227 size_t len = sizeof(val);
dkato 0:ee40da884cfc 228 if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
dkato 0:ee40da884cfc 229 disable_sse(info);
dkato 0:ee40da884cfc 230 else { /* double-check SSE2 */
dkato 0:ee40da884cfc 231 mib[1] = CPU_SSE2;
dkato 0:ee40da884cfc 232 len = sizeof(val);
dkato 0:ee40da884cfc 233 if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) {
dkato 0:ee40da884cfc 234 disable_sse(info);
dkato 0:ee40da884cfc 235 info->ia32.sse = true;
dkato 0:ee40da884cfc 236 }
dkato 0:ee40da884cfc 237 }
dkato 0:ee40da884cfc 238 # else
dkato 0:ee40da884cfc 239 disable_sse(info);
dkato 0:ee40da884cfc 240 # endif
dkato 0:ee40da884cfc 241 #elif defined(__linux__)
dkato 0:ee40da884cfc 242 int sse = 0;
dkato 0:ee40da884cfc 243 struct sigaction sigill_save;
dkato 0:ee40da884cfc 244 struct sigaction sigill_sse;
dkato 0:ee40da884cfc 245 sigill_sse.sa_sigaction = sigill_handler_sse_os;
dkato 0:ee40da884cfc 246 __sigemptyset(&sigill_sse.sa_mask);
dkato 0:ee40da884cfc 247 sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */
dkato 0:ee40da884cfc 248 if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save))
dkato 0:ee40da884cfc 249 {
dkato 0:ee40da884cfc 250 /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */
dkato 0:ee40da884cfc 251 /* see sigill_handler_sse_os() for an explanation of the following: */
dkato 0:ee40da884cfc 252 asm volatile (
dkato 0:ee40da884cfc 253 "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */
dkato 0:ee40da884cfc 254 "incl %0\n\t" /* SIGILL handler will jump over this */
dkato 0:ee40da884cfc 255 /* landing zone */
dkato 0:ee40da884cfc 256 "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */
dkato 0:ee40da884cfc 257 "nop\n\t"
dkato 0:ee40da884cfc 258 "nop\n\t"
dkato 0:ee40da884cfc 259 "nop\n\t"
dkato 0:ee40da884cfc 260 "nop\n\t"
dkato 0:ee40da884cfc 261 "nop\n\t"
dkato 0:ee40da884cfc 262 "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */
dkato 0:ee40da884cfc 263 "nop\n\t"
dkato 0:ee40da884cfc 264 "nop" /* SIGILL jump lands here if "inc" is 1 byte */
dkato 0:ee40da884cfc 265 : "=r"(sse)
dkato 0:ee40da884cfc 266 : "0"(sse)
dkato 0:ee40da884cfc 267 );
dkato 0:ee40da884cfc 268
dkato 0:ee40da884cfc 269 sigaction(SIGILL, &sigill_save, NULL);
dkato 0:ee40da884cfc 270 }
dkato 0:ee40da884cfc 271
dkato 0:ee40da884cfc 272 if(!sse)
dkato 0:ee40da884cfc 273 disable_sse(info);
dkato 0:ee40da884cfc 274 #elif defined(_MSC_VER)
dkato 0:ee40da884cfc 275 __try {
dkato 0:ee40da884cfc 276 __asm {
dkato 0:ee40da884cfc 277 xorps xmm0,xmm0
dkato 0:ee40da884cfc 278 }
dkato 0:ee40da884cfc 279 }
dkato 0:ee40da884cfc 280 __except(EXCEPTION_EXECUTE_HANDLER) {
dkato 0:ee40da884cfc 281 if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
dkato 0:ee40da884cfc 282 disable_sse(info);
dkato 0:ee40da884cfc 283 }
dkato 0:ee40da884cfc 284 #elif defined(__GNUC__) /* MinGW goes here */
dkato 0:ee40da884cfc 285 int sse = 0;
dkato 0:ee40da884cfc 286 /* Based on the idea described in Agner Fog's manual "Optimizing subroutines in assembly language" */
dkato 0:ee40da884cfc 287 /* In theory, not guaranteed to detect lack of OS SSE support on some future Intel CPUs, but in practice works (see the aforementioned manual) */
dkato 0:ee40da884cfc 288 if (ia32_fxsr) {
dkato 0:ee40da884cfc 289 struct {
dkato 0:ee40da884cfc 290 FLAC__uint32 buff[128];
dkato 0:ee40da884cfc 291 } __attribute__((aligned(16))) fxsr;
dkato 0:ee40da884cfc 292 FLAC__uint32 old_val, new_val;
dkato 0:ee40da884cfc 293
dkato 0:ee40da884cfc 294 asm volatile ("fxsave %0" : "=m" (fxsr) : "m" (fxsr));
dkato 0:ee40da884cfc 295 old_val = fxsr.buff[50];
dkato 0:ee40da884cfc 296 fxsr.buff[50] ^= 0x0013c0de; /* change value in the buffer */
dkato 0:ee40da884cfc 297 asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* try to change SSE register */
dkato 0:ee40da884cfc 298 fxsr.buff[50] = old_val; /* restore old value in the buffer */
dkato 0:ee40da884cfc 299 asm volatile ("fxsave %0 " : "=m" (fxsr) : "m" (fxsr)); /* old value will be overwritten if SSE register was changed */
dkato 0:ee40da884cfc 300 new_val = fxsr.buff[50]; /* == old_val if FXRSTOR didn't change SSE register and (old_val ^ 0x0013c0de) otherwise */
dkato 0:ee40da884cfc 301 fxsr.buff[50] = old_val; /* again restore old value in the buffer */
dkato 0:ee40da884cfc 302 asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* restore old values of registers */
dkato 0:ee40da884cfc 303
dkato 0:ee40da884cfc 304 if ((old_val^new_val) == 0x0013c0de)
dkato 0:ee40da884cfc 305 sse = 1;
dkato 0:ee40da884cfc 306 }
dkato 0:ee40da884cfc 307 if(!sse)
dkato 0:ee40da884cfc 308 disable_sse(info);
dkato 0:ee40da884cfc 309 #else
dkato 0:ee40da884cfc 310 /* no way to test, disable to be safe */
dkato 0:ee40da884cfc 311 disable_sse(info);
dkato 0:ee40da884cfc 312 #endif
dkato 0:ee40da884cfc 313 #ifdef DEBUG
dkato 0:ee40da884cfc 314 fprintf(stderr, " SSE OS sup . %c\n", info->ia32.sse ? 'Y' : 'n');
dkato 0:ee40da884cfc 315 #endif
dkato 0:ee40da884cfc 316 }
dkato 0:ee40da884cfc 317 else /* info->ia32.sse == false */
dkato 0:ee40da884cfc 318 disable_sse(info);
dkato 0:ee40da884cfc 319
dkato 0:ee40da884cfc 320 /*
dkato 0:ee40da884cfc 321 * now have to check for OS support of AVX instructions
dkato 0:ee40da884cfc 322 */
dkato 0:ee40da884cfc 323 if(info->ia32.avx && ia32_osxsave) {
dkato 0:ee40da884cfc 324 FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
dkato 0:ee40da884cfc 325 if ((ecr & 0x6) != 0x6)
dkato 0:ee40da884cfc 326 disable_avx(info);
dkato 0:ee40da884cfc 327 #ifdef DEBUG
dkato 0:ee40da884cfc 328 fprintf(stderr, " AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n');
dkato 0:ee40da884cfc 329 #endif
dkato 0:ee40da884cfc 330 }
dkato 0:ee40da884cfc 331 else /* no OS AVX support*/
dkato 0:ee40da884cfc 332 disable_avx(info);
dkato 0:ee40da884cfc 333 #else
dkato 0:ee40da884cfc 334 info->use_asm = false;
dkato 0:ee40da884cfc 335 #endif
dkato 0:ee40da884cfc 336
dkato 0:ee40da884cfc 337 /*
dkato 0:ee40da884cfc 338 * x86-64-specific
dkato 0:ee40da884cfc 339 */
dkato 0:ee40da884cfc 340 #elif defined FLAC__CPU_X86_64
dkato 0:ee40da884cfc 341 FLAC__bool x86_osxsave = false;
dkato 0:ee40da884cfc 342 (void) x86_osxsave; /* to avoid warnings about unused variables */
dkato 0:ee40da884cfc 343 memset(info, 0, sizeof(*info));
dkato 0:ee40da884cfc 344 info->type = FLAC__CPUINFO_TYPE_X86_64;
dkato 0:ee40da884cfc 345 #if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN
dkato 0:ee40da884cfc 346 info->use_asm = true;
dkato 0:ee40da884cfc 347 {
dkato 0:ee40da884cfc 348 /* http://www.sandpile.org/x86/cpuid.htm */
dkato 0:ee40da884cfc 349 FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
dkato 0:ee40da884cfc 350 FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
dkato 0:ee40da884cfc 351 info->x86.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
dkato 0:ee40da884cfc 352 info->x86.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
dkato 0:ee40da884cfc 353 info->x86.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
dkato 0:ee40da884cfc 354 info->x86.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
dkato 0:ee40da884cfc 355 #if defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 356 x86_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
dkato 0:ee40da884cfc 357 info->x86.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false;
dkato 0:ee40da884cfc 358 info->x86.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false;
dkato 0:ee40da884cfc 359 FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
dkato 0:ee40da884cfc 360 info->x86.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false;
dkato 0:ee40da884cfc 361 #endif
dkato 0:ee40da884cfc 362 }
dkato 0:ee40da884cfc 363 #ifdef DEBUG
dkato 0:ee40da884cfc 364 fprintf(stderr, "CPU info (x86-64):\n");
dkato 0:ee40da884cfc 365 fprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n');
dkato 0:ee40da884cfc 366 fprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
dkato 0:ee40da884cfc 367 fprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
dkato 0:ee40da884cfc 368 fprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
dkato 0:ee40da884cfc 369 # if defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 370 fprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n');
dkato 0:ee40da884cfc 371 fprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n');
dkato 0:ee40da884cfc 372 fprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n');
dkato 0:ee40da884cfc 373 # endif
dkato 0:ee40da884cfc 374 #endif
dkato 0:ee40da884cfc 375
dkato 0:ee40da884cfc 376 /*
dkato 0:ee40da884cfc 377 * now have to check for OS support of AVX instructions
dkato 0:ee40da884cfc 378 */
dkato 0:ee40da884cfc 379 if(info->x86.avx && x86_osxsave) {
dkato 0:ee40da884cfc 380 FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
dkato 0:ee40da884cfc 381 if ((ecr & 0x6) != 0x6)
dkato 0:ee40da884cfc 382 disable_avx(info);
dkato 0:ee40da884cfc 383 #ifdef DEBUG
dkato 0:ee40da884cfc 384 fprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
dkato 0:ee40da884cfc 385 #endif
dkato 0:ee40da884cfc 386 }
dkato 0:ee40da884cfc 387 else /* no OS AVX support*/
dkato 0:ee40da884cfc 388 disable_avx(info);
dkato 0:ee40da884cfc 389 #else
dkato 0:ee40da884cfc 390 info->use_asm = false;
dkato 0:ee40da884cfc 391 #endif
dkato 0:ee40da884cfc 392
dkato 0:ee40da884cfc 393 /*
dkato 0:ee40da884cfc 394 * unknown CPU
dkato 0:ee40da884cfc 395 */
dkato 0:ee40da884cfc 396 #else
dkato 0:ee40da884cfc 397 info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
dkato 0:ee40da884cfc 398 info->use_asm = false;
dkato 0:ee40da884cfc 399 #endif
dkato 0:ee40da884cfc 400 }
dkato 0:ee40da884cfc 401
dkato 0:ee40da884cfc 402 #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
dkato 0:ee40da884cfc 403
dkato 0:ee40da884cfc 404 #if defined _MSC_VER
dkato 0:ee40da884cfc 405 #include <intrin.h> /* for __cpuid() and _xgetbv() */
dkato 0:ee40da884cfc 406 #elif defined __GNUC__ && defined HAVE_CPUID_H
dkato 0:ee40da884cfc 407 #include <cpuid.h> /* for __get_cpuid() and __get_cpuid_max() */
dkato 0:ee40da884cfc 408 #endif
dkato 0:ee40da884cfc 409
dkato 0:ee40da884cfc 410 FLAC__uint32 FLAC__cpu_have_cpuid_x86(void)
dkato 0:ee40da884cfc 411 {
dkato 0:ee40da884cfc 412 #ifdef FLAC__CPU_X86_64
dkato 0:ee40da884cfc 413 return 1;
dkato 0:ee40da884cfc 414 #else
dkato 0:ee40da884cfc 415 # if defined _MSC_VER || defined __INTEL_COMPILER /* Do they support CPUs w/o CPUID support (or OSes that work on those CPUs)? */
dkato 0:ee40da884cfc 416 FLAC__uint32 flags1, flags2;
dkato 0:ee40da884cfc 417 __asm {
dkato 0:ee40da884cfc 418 pushfd
dkato 0:ee40da884cfc 419 pushfd
dkato 0:ee40da884cfc 420 pop eax
dkato 0:ee40da884cfc 421 mov flags1, eax
dkato 0:ee40da884cfc 422 xor eax, 0x200000
dkato 0:ee40da884cfc 423 push eax
dkato 0:ee40da884cfc 424 popfd
dkato 0:ee40da884cfc 425 pushfd
dkato 0:ee40da884cfc 426 pop eax
dkato 0:ee40da884cfc 427 mov flags2, eax
dkato 0:ee40da884cfc 428 popfd
dkato 0:ee40da884cfc 429 }
dkato 0:ee40da884cfc 430 if (((flags1^flags2) & 0x200000) != 0)
dkato 0:ee40da884cfc 431 return 1;
dkato 0:ee40da884cfc 432 else
dkato 0:ee40da884cfc 433 return 0;
dkato 0:ee40da884cfc 434 # elif defined __GNUC__ && defined HAVE_CPUID_H
dkato 0:ee40da884cfc 435 if (__get_cpuid_max(0, 0) != 0)
dkato 0:ee40da884cfc 436 return 1;
dkato 0:ee40da884cfc 437 else
dkato 0:ee40da884cfc 438 return 0;
dkato 0:ee40da884cfc 439 # else
dkato 0:ee40da884cfc 440 return 0;
dkato 0:ee40da884cfc 441 # endif
dkato 0:ee40da884cfc 442 #endif
dkato 0:ee40da884cfc 443 }
dkato 0:ee40da884cfc 444
dkato 0:ee40da884cfc 445 void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx)
dkato 0:ee40da884cfc 446 {
dkato 0:ee40da884cfc 447 #if defined _MSC_VER || defined __INTEL_COMPILER
dkato 0:ee40da884cfc 448 int cpuinfo[4];
dkato 0:ee40da884cfc 449 int ext = level & 0x80000000;
dkato 0:ee40da884cfc 450 __cpuid(cpuinfo, ext);
dkato 0:ee40da884cfc 451 if((unsigned)cpuinfo[0] < level) {
dkato 0:ee40da884cfc 452 *eax = *ebx = *ecx = *edx = 0;
dkato 0:ee40da884cfc 453 return;
dkato 0:ee40da884cfc 454 }
dkato 0:ee40da884cfc 455 #if defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 456 __cpuidex(cpuinfo, level, 0); /* for AVX2 detection */
dkato 0:ee40da884cfc 457 #else
dkato 0:ee40da884cfc 458 __cpuid(cpuinfo, level); /* some old compilers don't support __cpuidex */
dkato 0:ee40da884cfc 459 #endif
dkato 0:ee40da884cfc 460 *eax = cpuinfo[0]; *ebx = cpuinfo[1]; *ecx = cpuinfo[2]; *edx = cpuinfo[3];
dkato 0:ee40da884cfc 461 #elif defined __GNUC__ && defined HAVE_CPUID_H
dkato 0:ee40da884cfc 462 FLAC__uint32 ext = level & 0x80000000;
dkato 0:ee40da884cfc 463 __cpuid(ext, *eax, *ebx, *ecx, *edx);
dkato 0:ee40da884cfc 464 if (*eax < level) {
dkato 0:ee40da884cfc 465 *eax = *ebx = *ecx = *edx = 0;
dkato 0:ee40da884cfc 466 return;
dkato 0:ee40da884cfc 467 }
dkato 0:ee40da884cfc 468 __cpuid_count(level, 0, *eax, *ebx, *ecx, *edx);
dkato 0:ee40da884cfc 469 #else
dkato 0:ee40da884cfc 470 *eax = *ebx = *ecx = *edx = 0;
dkato 0:ee40da884cfc 471 #endif
dkato 0:ee40da884cfc 472 }
dkato 0:ee40da884cfc 473
dkato 0:ee40da884cfc 474 FLAC__uint32 FLAC__cpu_xgetbv_x86(void)
dkato 0:ee40da884cfc 475 {
dkato 0:ee40da884cfc 476 #if (defined _MSC_VER || defined __INTEL_COMPILER) && defined FLAC__AVX_SUPPORTED
dkato 0:ee40da884cfc 477 return (FLAC__uint32)_xgetbv(0);
dkato 0:ee40da884cfc 478 #elif defined __GNUC__
dkato 0:ee40da884cfc 479 FLAC__uint32 lo, hi;
dkato 0:ee40da884cfc 480 asm volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0));
dkato 0:ee40da884cfc 481 return lo;
dkato 0:ee40da884cfc 482 #else
dkato 0:ee40da884cfc 483 return 0;
dkato 0:ee40da884cfc 484 #endif
dkato 0:ee40da884cfc 485 }
dkato 0:ee40da884cfc 486
dkato 0:ee40da884cfc 487 #endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */