|
SASC
DVBSoftCAM
|
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 }