gps/GPSResources/tcpmp/common/dyncode/dyncode_sh3.c

332 lines
7.4 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: dyncode_sh3.c 585 2006-01-16 09:48:55Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#include "dyncode.h"
#if defined(SH3) && defined(CONFIG_DYNCODE)
//format coded in 'code' at 16bit position
//00: rn,imm
//01: rn,label,disp8*2
//02: rn,label,disp8*4
//03: rm,rn
//04: rn,disp4*1
//05: rn,disp4*2
//06: rm,rn,disp4*4
//07: rn
//08: imm
//09: -
//0A: label8
//0B: label12
//0C: rn (branch)
//0D: - (branch)
//read at 20bit / write at 24bit
//01: r1
//02: r2
//04: R0
//08: T
//spec at 28bit
//01: read mac
//02: read pr
//04: write mac
//08: write pr
static INLINE int Format(int i) { return (i >> 16) & 15; }
static INLINE int C(int i) { return i & 0xFFFF; }
void InstInit()
{
}
void InstPost(dyninst* p)
{
context* c = Context();
InstAdd(p,c);
}
void PostAdj(dyninst* p,int Code,reg Rn,reg Rm)
{
if (p)
{
if (Code & (1<<20)) p->RdRegs |= 1 << Rn;
if (Code & (2<<20)) p->RdRegs |= 1 << Rm;
if (Code & (4<<20)) p->RdRegs |= 1 << R0;
if (Code & (1<<28)) p->RdRegs |= 1 << MACL;
if (Code & (2<<28)) p->RdRegs |= 1 << PR;
p->RdFlags = Code & (8<<20) ? 1:0;
if (Code & (1<<24)) p->WrRegs |= 1 << Rn;
if (Code & (2<<24)) p->WrRegs |= 1 << Rm;
if (Code & (4<<24)) p->WrRegs |= 1 << R0;
if (Code & (4<<28)) p->WrRegs |= 1 << MACL;
if (Code & (8<<28)) p->WrRegs |= 1 << PR;
p->WrFlags = Code & (8<<24) ? 1:0;
}
InstPost(p);
}
void IShift(reg Rn, reg Tmp, int Left)
{
switch (Left)
{
default:
if (Tmp != NONE)
{
I1C(MOVI,Tmp,Left);
I2(SHLD,Tmp,Rn);
break;
}
// no break;
case 16+8:
case 16+2:
case 16+1:
case 16:
case 8+2:
case 8+1:
case 8:
case 2+1:
case 2:
case 1:
case 0:
case -16-8:
case -16-2:
case -16-1:
case -16:
case -8-2:
case -8-1:
case -8:
case -2-1:
case -2:
case -1:
while (Left <= -16) { I1(SHLR16,Rn); Left += 16; }
while (Left >= 16) { I1(SHLL16,Rn); Left -= 16; }
while (Left <= -8) { I1(SHLR8,Rn); Left += 8; }
while (Left >= 8) { I1(SHLL8,Rn); Left -= 8; }
while (Left <= -2) { I1(SHLR2,Rn); Left += 2; }
while (Left >= 2) { I1(SHLL2,Rn); Left -= 2; }
while (Left <= -1) { I1(SHLR,Rn); Left += 1; }
while (Left >= 1) { I1(SHLL,Rn); Left -= 1; }
break;
}
}
void I0C(int Code, int Const)
{
dyninst* p = NULL;
if (Format(Code)==8 && Const >= -128 && Const <= 127)
p = InstCreate16(C(Code) | (Const & 255),NONE,NONE,NONE,0,0);
if (Format(Code)==9 && Const == 0)
p = InstCreate16(C(Code),NONE,NONE,NONE,0,0);
if (Format(Code)==13 && Const == 0)
{
p = InstCreate16(C(Code),NONE,NONE,NONE,0,0);
if (p)
p->Branch = 1;
}
PostAdj(p,Code,NONE,NONE);
}
void I0(int Code)
{
I0C(Code,0);
}
void I1C(int Code, reg Rn, int Const)
{
dyninst* p = NULL;
if (Format(Code)==0 && Const >= -128 && Const <= 127)
p = InstCreate16(C(Code) | (Rn << 8) | (Const & 255),NONE,NONE,NONE,0,0);
if (Format(Code)==4 && Const >= -8 && Const <= 7)
p = InstCreate16(C(Code) | (Rn << 4) | (Const & 15),NONE,NONE,NONE,0,0);
if (Format(Code)==5 && !(Const & 1) && Const >= -16 && Const <= 14)
p = InstCreate16(C(Code) | (Rn << 4) | ((Const >> 1) & 15),NONE,NONE,NONE,0,0);
if (Format(Code)==7 && Const == 0)
p = InstCreate16(C(Code) | (Rn << 8),NONE,NONE,NONE,0,0);
if (Format(Code)==12 && Const == 0)
{
p = InstCreate16(C(Code) | (Rn << 8),NONE,NONE,NONE,0,0);
if (p)
p->Branch = 1;
}
PostAdj(p,Code,Rn,NONE);
}
void I1(int Code, reg Rn)
{
I1C(Code,Rn,0);
}
void I2C(int Code, reg Rm, reg Rn, int Const)
{
dyninst* p = NULL;
if (Format(Code)==3 && Const == 0)
p = InstCreate16(C(Code) | (Rn << 8) | (Rm << 4),NONE,NONE,NONE,0,0);
if (Format(Code)==6 && !(Const & 3) && Const >= -32 && Const <= 28)
p = InstCreate16(C(Code) | (Rn << 8) | (Rm << 4) | ((Const >> 2) & 15),NONE,NONE,NONE,0,0);
PostAdj(p,Code,Rm,Rn);
}
void I2(int Code, reg Rm, reg Rn)
{
I2C(Code,Rm,Rn,0);
}
dyninst* ICode(dyninst* Block, int Ofs)
{
dyninst* p = InstCreate32(Ofs,NONE,NONE,NONE,0,0);
if (p)
{
p->Tag = -1;
p->ReAlloc = Block;
p->Branch = 1;
}
return p;
}
void I1P(int Code, reg Rn, dyninst* Block, int Ofs)
{
dyninst* p = NULL;
if (Format(Code)==1 && !(Ofs & 1) && Ofs >= -128*2 && Ofs <= 127*2)
{
p = InstCreate16(C(Code) | (Rn << 8) | ((Ofs >> 1) & 255),Rn,NONE,NONE,0,0);
if (p)
{
p->Tag = Format(Code);
p->ReAlloc = Block;
p->Branch = 1;
}
}
if (Format(Code)==2 && !(Ofs & 3) && Ofs >= -128*4 && Ofs <= 127*4)
{
p = InstCreate16(C(Code) | (Rn << 8) | ((Ofs >> 2) & 255),Rn,NONE,NONE,0,0);
if (p)
{
p->Tag = Format(Code);
p->ReAlloc = Block;
p->Branch = 1;
}
}
PostAdj(p,Code,Rn,NONE);
}
void I0P(int Code, dyninst* Block)
{
dyninst* p = NULL;
if (Format(Code)==10 || Format(Code)==11)
{
p = InstCreate16(C(Code),NONE,NONE,NONE,0,0);
if (p)
{
p->Tag = Format(Code);
p->ReAlloc = Block;
p->Branch = 1;
}
}
PostAdj(p,Code,NONE,NONE);
}
bool_t InstReAlloc(dyninst* p,dyninst* ReAlloc)
{
int Diff = ReAlloc->Address - (p->Address+4);
uint16_t* Code = (uint16_t*) InstCode(p);
Diff >>= 1;
assert(p->Tag == 10 || p->Tag == 1 || p->Tag == 2 || p->Tag == 11 || p->Tag == -1);
if (p->Tag == -1) // 32bit code address
{
*(uint32_t*)Code += (uint32_t)ReAlloc->Address;
return 1;
}
else
if (p->Tag == 10 || p->Tag == 1 || p->Tag == 2) //8bit
{
if (p->Tag == 2)
{
assert(((int)ReAlloc->Address & 3)==0);
Diff = ((int)ReAlloc->Address >> 2) - (((int)p->Address+4) >> 2);
}
Diff += *(int8_t*)Code;
assert(Diff <= 127 && Diff >= -128);
if (Diff > 127 || Diff < -128)
return 0;
*Code &= 0xFF00;
*Code |= (uint16_t)(Diff & 0xFF);
return 1;
}
else
if (p->Tag == 11) //12bit
{
assert(Diff <= 2047 && Diff >= -2048);
if (Diff > 2047 || Diff < -2048)
return 0;
*Code &= 0xF000;
*Code |= (uint16_t)(Diff & 0xFFF);
return 1;
}
return 0;
}
void CodeBegin(int Save,int Local)
{
int i;
assert(Save <= 7);
for (i=0;i<Save;++i)
I2(MOVL_STSUB,(reg)(R8+i),SP);
if (Local)
I1C(ADDI,SP,-Local);
}
void CodeEnd(int Save,int Local)
{
int i;
assert(Save <= 7);
if (Local)
I1C(ADDI,SP,Local);
for (i=Save-1;i>=0;--i)
I2(MOVL_LDADD,SP,(reg)(R8+i));
DS(); I0(RTS);
}
void NOP()
{
dyninst* p = InstCreate16(0x0009,NONE,NONE,NONE,0,0);
if (p)
p->Branch = 1;
InstPost(p);
}
void Break()
{
dyninst* p = InstCreate16(0xC300,NONE,NONE,NONE,0,0);
if (p)
p->Branch = 1;
InstPost(p);
}
#endif