gps/GPSResources/tcpmp/common/pcm/pcm_arm.c

425 lines
8.0 KiB
C
Executable File

/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: pcm_arm.c 304 2005-10-20 11:02:59Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#include "../dyncode/dyncode.h"
#include "pcm_soft.h"
#if defined(ARM)
typedef struct stack
{
int StackFrame[STACKFRAME];
//void* this R0
//plane Dst R1
//plane Src R2
//int DstLength R3
pcmstate* State;
int Volume;
} stack;
// R0,R1 dither
// R2,R3 value
// R4 Min
// R5 Max
// R6 tmp
// R7 Step
// R8 Pos
// R9 SrcLeft
// R10 SrcRight
// R11 DstLeft
// R12 DstRight
// R14 DstLeftEnd
void PCMLoop(pcm_soft* p,bool_t Speed)
{
dyninst* Loop;
reg Left;
reg Right;
Loop = Label(1);
Left = R2;
if (p->UseLeft)
Right = R3;
else
Right = R2;
if (Speed)
{
I3S(MOV,R3,NONE,R8,LSR,8);
switch (p->Src.Bits)
{
case 8:
if (p->SrcUnsigned)
{
if (p->UseLeft)
{
Byte(); I3S(LDR,Left,R9,R3,LSL,p->SrcShift);
}
if (p->UseRight)
{
Byte(); I3S(LDR,Right,R10,R3,LSL,p->SrcShift);
}
}
else
{
I3S(MOV,R3,NONE,R3,LSL,p->SrcShift);
if (p->UseLeft)
{
SByte(); I3(LDR,Left,R9,R3);
}
if (p->UseRight)
{
SByte(); I3(LDR,Right,R10,R3);
}
}
break;
case 16:
I3S(MOV,R3,NONE,R3,LSL,p->SrcShift);
if (p->UseLeft)
{
if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
I3(LDR,Left,R9,R3);
if (p->SrcSwap)
{
I3S(MOV,R6,NONE,Left,LSL,24);
I3S(MOV,Left,NONE,Left,LSR,8);
if (p->SrcUnsigned)
I3S(ORR,Left,Left,R6,LSR,16);
else
I3S(ORR,Left,Left,R6,ASR,16);
}
}
if (p->UseRight)
{
if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
I3(LDR,Right,R10,R3);
if (p->SrcSwap)
{
I3S(MOV,R6,NONE,Right,LSL,24);
I3S(MOV,Right,NONE,Right,LSR,8);
if (p->SrcUnsigned)
I3S(ORR,Right,Right,R6,LSR,16);
else
I3S(ORR,Right,Right,R6,ASR,16);
}
}
break;
case 32:
if (p->UseLeft)
I3S(LDR,Left,R9,R3,LSL,p->SrcShift);
if (p->UseRight)
I3S(LDR,Right,R10,R3,LSL,p->SrcShift);
break;
}
I3(ADD,R8,R8,R7);
}
else
{
switch (p->Src.Bits)
{
case 8:
if (p->UseLeft)
{
if (p->SrcUnsigned) Byte(); else SByte();
I2C(LDR_POST,Left,R9,1<<p->SrcShift);
}
if (p->UseRight)
{
if (p->SrcUnsigned) Byte(); else SByte();
I2C(LDR_POST,Right,R10,1<<p->SrcShift);
}
break;
case 16:
if (p->UseLeft)
{
if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
I2C(LDR_POST,Left,R9,1<<p->SrcShift);
if (p->SrcSwap)
{
I3S(MOV,R6,NONE,Left,LSL,24);
I3S(MOV,Left,NONE,Left,LSR,8);
if (p->SrcUnsigned)
I3S(ORR,Left,Left,R6,LSR,16);
else
I3S(ORR,Left,Left,R6,ASR,16);
}
}
if (p->UseRight)
{
if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
I2C(LDR_POST,Right,R10,1<<p->SrcShift);
if (p->SrcSwap)
{
I3S(MOV,R6,NONE,Right,LSL,24);
I3S(MOV,Right,NONE,Right,LSR,8);
if (p->SrcUnsigned)
I3S(ORR,Right,Right,R6,LSR,16);
else
I3S(ORR,Right,Right,R6,ASR,16);
}
}
break;
case 32:
if (p->UseLeft)
I2C(LDR_POST,Left,R9,1<<p->SrcShift);
if (p->UseRight)
I2C(LDR_POST,Right,R10,1<<p->SrcShift);
break;
}
}
if (p->SrcUnsigned)
{
I2C(SUB,R2,R2,p->SrcUnsigned);
if (p->SrcChannels>1)
I2C(SUB,R3,R3,p->SrcUnsigned);
}
if (p->Stereo)
{
if ((p->Src.Flags ^ p->Dst.Flags) & PCM_SWAPPEDSTEREO)
{
Left = R3;
Right = R2;
}
else
{
Left = R2;
Right = R3;
}
}
else
{
if (p->Join)
I3(ADD,R2,R2,R3);
Right = Left = R2;
}
if (p->ActualDither)
{
I3(ADD,R2,R2,R0);
I3(MOV,R0,NONE,R2);
if (p->Stereo)
{
I3(ADD,R3,R3,R1);
I3(MOV,R1,NONE,R3);
}
}
if (p->UseVolume)
{
if (p->Src.Bits >= 23)
I3S(MOV,R2,NONE,R2,ASR,8);
I3(MUL,R2,R0,R2);
if (p->Stereo)
{
if (p->Src.Bits >= 23)
I3S(MOV,R3,NONE,R3,ASR,8);
I3(MUL,R3,R0,R3);
}
}
if (p->Clip>0)
{
I3(CMP,NONE,R2,R4);
C(LT); I3(MOV,R2,NONE,R4);
I3(CMP,NONE,R2,R5);
C(GT); I3(MOV,R2,NONE,R5);
if (p->Stereo)
{
I3(CMP,NONE,R3,R4);
C(LT); I3(MOV,R3,NONE,R4);
I3(CMP,NONE,R3,R5);
C(GT); I3(MOV,R3,NONE,R5);
}
}
if (p->Shift)
{
I3S(MOV,R2,NONE,R2,ASR,-p->Shift);
if (p->Stereo) I3S(MOV,R3,NONE,R3,ASR,-p->Shift);
}
#ifdef TARGET_PALMOS
if (p->LifeDriveFix)
{
I3S(ADD,R6,R2,R1,LSL,1);
I3S(CMP,NONE,R6,R1,LSL,2);
C(LS); I2C(ORR,R2,R2,R0);
if (p->Stereo)
{
I3S(ADD,R6,R3,R1,LSL,1);
I3S(CMP,NONE,R6,R1,LSL,2);
C(LS); I3(ORR,R3,R3,R0);
}
}
#endif
if (p->ActualDither)
{
I3S(SUB,R0,R0,R2,ASR,p->Shift);
if (p->Stereo) I3S(SUB,R1,R1,R3,ASR,p->Shift);
}
if (p->DstUnsigned)
{
I2C(ADD,Left,Left,p->DstUnsigned);
if (Left != Right)
I2C(ADD,Right,Right,p->DstUnsigned);
}
switch (p->Dst.Bits)
{
case 8:
Byte(); I2C(STR_POST,Left,R11,1<<p->DstShift);
if (p->Dst.Channels>1)
{
Byte(); I2C(STR_POST,Right,R12,1<<p->DstShift);
}
break;
case 16:
Half(); I2C(STR_POST,Left,R11,1<<p->DstShift);
if (p->Dst.Channels>1)
{
Half(); I2C(STR_POST,Right,R12,1<<p->DstShift);
}
break;
case 32:
I2C(STR_POST,Left,R11,1<<p->DstShift);
if (p->Dst.Channels>1)
I2C(STR_POST,Right,R12,1<<p->DstShift);
break;
}
I3(CMP,NONE,R11,R14);
I0P(B,NE,Loop);
if (p->ActualDither)
{
I2C(LDR,R4,SP,OFS(stack,State));
I2C(STR,R0,R4,OFS(pcmstate,Dither[0]));
I2C(STR,R1,R4,OFS(pcmstate,Dither[1]));
}
CodeEnd();
}
void PCMCompile(pcm_soft* p)
{
dyninst* Speed;
dyninst* Min = NULL;
dyninst* Max = NULL;
CodeBegin();
// dst pointers
I2C(LDR,R11,R1,0);
if (p->Dst.Channels > 1)
{
if (p->Dst.Flags & PCM_PLANES)
I2C(LDR,R12,R1,4);
else
I2C(ADD,R12,R11,1<<(p->DstShift-1));
}
I3(ADD,R14,R11,R3); // dstend
// src pointers
I2C(LDR,R9,R2,0);
if (p->Src.Channels > 1)
{
if (p->Src.Flags & PCM_PLANES)
I2C(LDR,R10,R2,4);
else
I2C(ADD,R10,R9,p->Src.Bits>>3);
}
I2C(LDR,R4,SP,OFS(stack,State));
I2C(LDR,R7,R4,OFS(pcmstate,Step));
I2C(LDR,R8,R4,OFS(pcmstate,Pos));
#ifdef TARGET_PALMOS
if (p->LifeDriveFix)
{
I2C(LDR,R1,SP,OFS(stack,Volume));
I2C(MOV,R0,NONE,63);
I2C(CMP,NONE,R1,25);
C(GT); I2C(MOV,R0,NONE,31);
I2C(CMP,NONE,R1,50);
C(GT); I2C(MOV,R0,NONE,15);
I2C(CMP,NONE,R1,100);
C(GT); I2C(MOV,R0,NONE,7);
I2C(CMP,NONE,R1,200);
C(GT); I2C(MOV,R0,NONE,3);
I2C(ADD,R1,R0,1);
}
#endif
if (p->UseVolume)
I2C(LDR,R0,SP,OFS(stack,Volume));
if (p->ActualDither)
{
I2C(LDR,R0,R4,OFS(pcmstate,Dither[0]));
I2C(LDR,R1,R4,OFS(pcmstate,Dither[1]));
}
if (p->Clip>0)
{
Min = InstCreate32(p->MinLimit,NONE,NONE,NONE,0,0);
Max = InstCreate32(p->MaxLimit,NONE,NONE,NONE,0,0);
I1P(LDR,R4,Min,0);
I1P(LDR,R5,Max,0);
}
Speed = Label(0);
I2C(CMP,NONE,R7,256);
I0P(B,NE,Speed);
PCMLoop(p,0);
InstPost(Speed);
PCMLoop(p,1);
if (Min) InstPost(Min);
if (Max) InstPost(Max);
}
#endif