SASC-NG
DVBSoftCAM

st20.c

Go to the documentation of this file.
00001 /*
00002  * Softcam plugin to VDR (C++)
00003  *
00004  * This code is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This code is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
00018  */
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <string.h>
00023 
00024 #include <vdr/tools.h>
00025 
00026 #include "log-viaccess.h"
00027 #include "st20.h"
00028 
00029 #include "helper.h"
00030 #include "misc.h"
00031 
00032 //#define SAVE_DEBUG // add some (slow) failsafe checks and stricter emulation
00033 
00034 #define INVALID_VALUE   0xCCCCCCCC
00035 #define ERRORVAL        0xDEADBEEF
00036 
00037 #define MININT          0x7FFFFFFF
00038 #define MOSTPOS         0x7FFFFFFF
00039 #define MOSTNEG         0x80000000
00040 
00041 #ifndef SAVE_DEBUG
00042 #define POP() stack[(sptr++)&STACKMASK]
00043 #else
00044 #define POP() ({ int __t=stack[sptr&STACKMASK]; stack[(sptr++)&STACKMASK]=INVALID_VALUE; __t; })
00045 #endif
00046 #define PUSH(v) do { int __v=(v); stack[(--sptr)&STACKMASK]=__v; } while(0)
00047 #define DROP(n) sptr+=n
00048 
00049 #define AAA stack[sptr&STACKMASK]
00050 #define BBB stack[(sptr+1)&STACKMASK]
00051 #define CCC stack[(sptr+2)&STACKMASK]
00052 
00053 #define GET_OP()        operand|=op1&0x0F
00054 #define CLEAR_OP()      operand=0
00055 #define JUMP(x)         Iptr+=(x)
00056 #define POP64()         ({ unsigned int __b=POP(); ((unsigned long long)POP()<<32)|__b; })
00057 #define PUSHPOP(op,val) do { int __a=val; AAA op##= (__a); } while(0)
00058 
00059 #ifndef SAVE_DEBUG
00060 #define RB(off) UINT8_LE(Addr(off))
00061 #define RW(off) UINT32_LE(Addr(off))
00062 #define WW(off,val) BYTE4_LE(Addr(off),val)
00063 #else
00064 #define RB(off) ReadByte(off)
00065 #define RW(off) ReadWord(off)
00066 #define WW(off,val) WriteWord(off,val)
00067 #endif
00068 
00069 #define LOG_OP(op) do { if(v) LogOp(op); } while(0)
00070 
00071 // -- cST20 --------------------------------------------------------------------
00072 
00073 cST20::cST20(void)
00074 {
00075   flash=ram=0;
00076   loglb=new cLineBuff(128);
00077 }
00078 
00079 cST20::~cST20()
00080 {
00081   free(flash);
00082   free(ram);
00083   delete loglb;
00084 }
00085 
00086 void cST20::SetFlash(unsigned char *m, int len)
00087 {
00088   free(flash);
00089   flash=MALLOC(unsigned char,len);
00090   if(flash && m) memcpy(flash,m,len);
00091   else memset(flash,0,len);
00092   flashSize=len;
00093 }
00094 
00095 void cST20::SetRam(unsigned char *m, int len)
00096 {
00097   free(ram);
00098   ram=MALLOC(unsigned char,len);
00099   if(ram && m) memcpy(ram,m,len);
00100   else memset(ram,0,len);
00101   ramSize=len;
00102 }
00103 
00104 void cST20::Init(unsigned int IPtr, unsigned int WPtr)
00105 {
00106   Wptr=WPtr; Iptr=IPtr;
00107   memset(stack,INVALID_VALUE,sizeof(stack)); sptr=STACKMAX-3;
00108   memset(iram,0,sizeof(iram));
00109   verbose=LOG(L_SYS_DISASM);
00110 }
00111 
00112 void cST20::SetCallFrame(unsigned int raddr, int p1, int p2, int p3)
00113 {
00114   Wptr-=16;
00115   WriteWord(Wptr,raddr); // RET
00116   WriteWord(Wptr+4,0);
00117   WriteWord(Wptr+8,0);
00118   WriteWord(Wptr+12,p1);
00119   WriteWord(Wptr+16,p2);
00120   WriteWord(Wptr+20,p3);
00121   SetReg(AREG,raddr);    // RET
00122 }
00123 
00124 unsigned int cST20::GetReg(int reg) const
00125 {
00126   switch(reg) {
00127     case IPTR: return Iptr;
00128     case WPTR: return Wptr;
00129     case AREG: return AAA;
00130     case BREG: return BBB;
00131     case CREG: return CCC;
00132     default:   PRINTF(L_SYS_ST20,"getreg: unknown reg"); return ERRORVAL;
00133     }
00134 }
00135 
00136 void cST20::SetReg(int reg, unsigned int val)
00137 {
00138   switch(reg) {
00139     case IPTR: Iptr=val; return;
00140     case WPTR: Wptr=val; return;
00141     case AREG: AAA=val; return;
00142     case BREG: BBB=val; return;
00143     case CREG: CCC=val; return;
00144     default:   PRINTF(L_SYS_ST20,"setreg: unknown reg"); return;
00145     }
00146 }
00147 
00148 unsigned char *cST20::Addr(unsigned int off)
00149 {
00150   if(off>=FLASHS && off<=FLASHE) {
00151 #ifndef SAVE_DEBUG
00152     return &flash[off-FLASHS];
00153 #else
00154     off-=FLASHS; if(off<flashSize && flash) return &flash[off]; break;
00155 #endif
00156     }
00157   else if(off>=RAMS && off<=RAME) {
00158 #ifndef SAVE_DEBUG
00159     return &ram[off-RAMS];
00160 #else
00161     off-=RAMS; if(off<ramSize && ram) return &ram[off]; break;
00162 #endif
00163     }
00164   else if(off>=IRAMS && off<=IRAME)
00165     return &iram[off-IRAMS];
00166 #ifndef SAVE_DEBUG
00167   invalid=ERRORVAL; return (unsigned char *)&invalid;
00168 #else
00169   return 0;
00170 #endif
00171 }
00172 
00173 unsigned int cST20::ReadWord(unsigned int off)
00174 {
00175 #ifndef SAVE_DEBUG
00176   return UINT32_LE(Addr(off));
00177 #else
00178   unsigned char *addr=Addr(off);
00179   return addr ? UINT32_LE(addr) : ERRORVAL;
00180 #endif
00181 }
00182 
00183 unsigned short cST20::ReadShort(unsigned int off)
00184 {
00185 #ifndef SAVE_DEBUG
00186   return UINT16_LE(Addr(off));
00187 #else
00188   unsigned char *addr=Addr(off);
00189   return addr ? UINT16_LE(addr) : ERRORVAL>>16;
00190 #endif
00191 }
00192 
00193 unsigned char cST20::ReadByte(unsigned int off)
00194 {
00195 #ifndef SAVE_DEBUG
00196   return UINT8_LE(Addr(off));
00197 #else
00198   unsigned char *addr=Addr(off);
00199   return addr ? UINT8_LE(addr) : ERRORVAL>>24;
00200 #endif
00201 }
00202 
00203 void cST20::WriteWord(unsigned int off, unsigned int val)
00204 {
00205 #ifndef SAVE_DEBUG
00206   BYTE4_LE(Addr(off),val);
00207 #else
00208   unsigned char *addr=Addr(off);
00209   if(addr) BYTE4_LE(addr,val);
00210 #endif
00211 }
00212 
00213 void cST20::WriteShort(unsigned int off, unsigned short val)
00214 {
00215 #ifndef SAVE_DEBUG
00216   BYTE2_LE(Addr(off),val);
00217 #else
00218   unsigned char *addr=Addr(off);
00219   if(addr) BYTE2_LE(addr,val);
00220 #endif
00221 }
00222 
00223 void cST20::WriteByte(unsigned int off, unsigned char val)
00224 {
00225 #ifndef SAVE_DEBUG
00226   BYTE1_LE(Addr(off),val);
00227 #else
00228   unsigned char *addr=Addr(off);
00229   if(addr) BYTE1_LE(addr,val);
00230 #endif
00231 }
00232 
00233 #define OP_COL 20
00234 
00235 void cST20::LogOpOper(int op, int oper)
00236 {
00237   const static char *cmds[] = { "j","ldlp",0,"ldnl","ldc","ldnlp",0,"ldl","adc","call","cj","ajw","eqc","stl","stnl",0 };
00238   const static char flags[] = {  3,  0,    0, 0,     1,    0,     0, 0,    1,    3,     3,   0,    1,    0,    0,    0 };
00239   if(oper==0) loglb->Printf("%08X %02X",Iptr-1,op);
00240   else        loglb->Printf("%02X",op);
00241   oper|=op&0xF; op>>=4;
00242   if(!cmds[op]) return;
00243   int n=loglb->Length();
00244   if(flags[op]&2) oper+=Iptr;
00245   if(flags[op]&1) loglb->Printf("%*s%-5s $%-8X ",max(OP_COL-n,1)," ",cmds[op],oper);
00246   else            loglb->Printf("%*s%-5s  %-8d ",max(OP_COL-n,1)," ",cmds[op],oper);
00247 }
00248 
00249 void cST20::LogOp(const char *op)
00250 {
00251   int n=loglb->Length();
00252   loglb->Printf("%*s%-15s ",max(OP_COL-n,1)," ",op);
00253 }
00254 
00255 int cST20::Decode(int count)
00256 {
00257   int operand;
00258   bool v=verbose;
00259   CLEAR_OP();
00260   while(Iptr!=0) {
00261     int a, op1=RB(Iptr++);
00262     if(v) LogOpOper(op1,operand);
00263     GET_OP();
00264     switch(op1>>4) {
00265       case 0x0: // j / jump
00266 #ifdef SAVE_DEBUG
00267         POP(); POP(); POP();
00268 #endif
00269         JUMP(operand);
00270         CLEAR_OP();
00271         break;
00272       case 0x1: // ldlp
00273         PUSH(Wptr+(operand*4));
00274         CLEAR_OP();
00275         break;
00276       case 0x2: // positive prefix
00277         operand<<=4;
00278         break;
00279       case 0x3: // ldnl
00280         AAA=RW(AAA+(operand*4));
00281         CLEAR_OP();
00282         break;
00283       case 0x4: // ldc
00284         PUSH(operand);
00285         CLEAR_OP();
00286         break;
00287       case 0x5: // ldnlp
00288         PUSHPOP(+,operand*4);
00289         CLEAR_OP();
00290         break;
00291       case 0x6: // negative prefix
00292         operand=(~operand)<<4;
00293         break;
00294       case 0x7: // ldl
00295         PUSH(RW(Wptr+(operand*4)));
00296         CLEAR_OP();
00297         break;
00298       case 0x8: // adc
00299         PUSHPOP(+,operand);
00300         CLEAR_OP();
00301         break;
00302       case 0x9: // call
00303         Wptr-=16;
00304         WW(Wptr,Iptr); WW(Wptr+4,POP()); WW(Wptr+8,POP()); WW(Wptr+12,POP());
00305         PUSH(Iptr);
00306         JUMP(operand);
00307         CLEAR_OP();
00308         break;
00309       case 0xA: // cj / conditional jump
00310         if(AAA) DROP(1); else JUMP(operand);
00311         CLEAR_OP();
00312         break;
00313       case 0xB: // ajw / adjust workspace
00314         Wptr+=operand*4;
00315         CLEAR_OP();
00316         break;
00317       case 0xC: // eqc / equals constant
00318         AAA=(operand==AAA ? 1 : 0);
00319         CLEAR_OP();
00320         break;
00321       case 0xD: // stl
00322         WW(Wptr+(operand*4),POP());
00323         CLEAR_OP();
00324         break;
00325       case 0xE: // stnl
00326         a=POP(); WW(a+(operand*4),POP());
00327         CLEAR_OP();
00328         break;
00329       case 0xF: // opr (secondary ins)
00330         switch(operand) {
00331           case  0x00: LOG_OP("rev");   a=AAA; AAA=BBB; BBB=a; break;
00332           case  0x01: LOG_OP("lb");    AAA=RB(AAA); break;
00333           case  0x02: LOG_OP("bsub");  PUSHPOP(+,POP()); break;
00334           case  0x04: LOG_OP("diff");  PUSHPOP(-,POP()); break;
00335           case  0x05: LOG_OP("add");   PUSHPOP(+,POP()); break;
00336           case  0x06: LOG_OP("gcall"); a=AAA; AAA=Iptr; Iptr=a; break;
00337           case  0x08: LOG_OP("prod");  PUSHPOP(*,POP()); break;
00338           case  0x09: LOG_OP("gt");    a=POP(); AAA=(AAA>a); break;
00339           case  0x0A: LOG_OP("wsub");  a=POP(); AAA=a+(AAA*4); break;
00340           case  0x0C: LOG_OP("sub");   PUSHPOP(-,POP()); break;
00341 
00342           case  0x1B: LOG_OP("ldpi");  PUSHPOP(+,Iptr); break;
00343           case  0x20: LOG_OP("ret");   Iptr=RW(Wptr); Wptr=Wptr+16; break;
00344           case  0x2C: LOG_OP("div");   PUSHPOP(/,POP()); break;
00345           case  0x32: LOG_OP("not");   AAA=~AAA; break;
00346           case  0x33: LOG_OP("xor");   PUSHPOP(^,POP()); break;
00347           case  0x34: LOG_OP("bcnt");  PUSHPOP(*,4); break;
00348           case  0x3B: LOG_OP("sb");    a=POP(); WriteByte(a,POP()); break;
00349           case  0x3F: LOG_OP("wcnt");  a=POP(); PUSH(a&3); PUSH((unsigned int)a>>2); break;
00350           case  0x40: LOG_OP("shr");   a=POP(); AAA=(unsigned int)AAA>>a; break;
00351           case  0x41: LOG_OP("shl");   a=POP(); AAA=(unsigned int)AAA<<a; break;
00352           case  0x42: LOG_OP("mint");  PUSH(MOSTNEG); break;
00353           case  0x46: LOG_OP("and");   PUSHPOP(&,POP()); break;
00354           case  0x4A: LOG_OP("move");  { a=POP(); int b=POP(); int c=POP(); while(a--) WriteByte(b++,ReadByte(c++)); } break;
00355           case  0x4B: LOG_OP("or");    PUSHPOP(|,POP()); break;
00356           case  0x53: LOG_OP("mul");   PUSHPOP(*,POP()); break;
00357           case  0x5A: LOG_OP("dup");   PUSH(AAA); break;
00358           case  0x5F: LOG_OP("gtu");   a=POP(); AAA=((unsigned int)AAA>(unsigned int)a); break;
00359           case  0x1D: LOG_OP("xdble"); CCC=BBB; BBB=(AAA>=0 ? 0:-1); break;
00360           case  0x1A: LOG_OP("ldiv");  { a=POP(); unsigned long long ll=POP64(); PUSH(ll%(unsigned int)a); PUSH(ll/(unsigned int)a); } break;
00361           case  0x1F: LOG_OP("rem");   PUSHPOP(%,POP()); break;
00362           case  0x35: LOG_OP("lshr");  { a=POP(); unsigned long long ll=POP64()>>a; PUSH((ll>>32)&0xFFFFFFFF); PUSH(ll&0xFFFFFFFF); } break;
00363 
00364           case  0xCA: LOG_OP("ls");    AAA=ReadShort(AAA); break;
00365           case  0xCD: LOG_OP("gintdis"); break;
00366           case  0xCE: LOG_OP("gintenb"); break;
00367 
00368           case -0x40: LOG_OP("nop");   break;
00369 
00370           default: 
00371             if(verbose) PUTLB(L_SYS_DISASM,loglb);
00372             PRINTF(L_SYS_ST20,"unknown opcode %X",operand);
00373             return ERR_ILL_OP;
00374           }
00375         CLEAR_OP();
00376         break;
00377       }
00378 
00379     if(v && operand==0) {
00380       loglb->Printf("%08X %08X %08X W:%08X",AAA,BBB,CCC,Wptr);
00381       PUTLB(L_SYS_DISASM,loglb);
00382       }
00383     if(--count<=0 && operand==0) {
00384       PRINTF(L_SYS_ST20,"instruction counter exceeded");
00385       return ERR_CNT;
00386       }
00387     }
00388   return 0;
00389 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines