123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #!/usr/bin/php
- <?php
- /*
- * Copyright (C) 2017 bzt (bztsrc@gitlab)
- *
- * 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 3 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * @brief Quick and really dirty tool to generate C code from the instruction table in
- * the txt file. Don't try to understand this code, specially if your IQ is under 140!
- * Wild array indexing, php hacks and regular expressions ahead! You have been warned!
- */
- function sh($a,$s,$n,&$sho) { $l=count($a);foreach($a as $k=>$A) @$b[$A-($l-$k-1)]|=1<<($l-$k-1);$c=($s?"((ic".$n.(isset($sho[$n."_".$a[0]])?"_".$a[0]:($a[0]?">>".$a[0]:"")).
- ")&1?(0xffffffff<<".$l."):0)":"");foreach($b as $k=>$b) $c.=($c?"|":"")."((ic".$n.(isset($sho[$n."_".$k])?"_".$k:($k?">>".$k:"")).")&0x".dechex($b).")";return $c;}
- function b2h($b) { return base_convert($b,2,16); }
- $pre="disasm"; $copy=[]; $argdefc=[]; $argdef=[]; $in=[]; $out=[]; $list=['signext'=>['i','a0','a1']]; $mn=[]; $ar=[];
- $fn=@$_SERVER['argv'][1]; $hv=@$_SERVER['argv'][2]=='-v'; $ha=@$_SERVER['argv'][2]=='-a'; $hi=$_SERVER['argc']>2&&!$hv&&!$ha; $hn=@$_SERVER['argv'][3]=="-n"; $hs=$_SERVER['argc']>3&&!$hn;
- if(empty($fn)) die("Universal Disassember by bzt\n\n".$_SERVER['argv'][0]." <text file> [-v|-i|-a] [-s|-n]\n\n text file\t- an ascii text file with instruction table definitions\n -v\t\t- optional verbose flag, report unused definitions\n -i\t\t- add external variables for integration\n -a\t\t- code analysis report on instruction\n -s\t\t- sprintf returns char*\n -n\t\t- use snprintf with the additional size argument\n\nQuick and dirty script to convert ascii instruction table into a C header.\n");
- $data=str_replace("\r","",@file_get_contents($fn));preg_match_all("/\/\*.*?\*\//sm", $data, $m);
- if(!empty($m) && !empty($m[0])) foreach($m[0] as $c) $data=str_replace($c,str_repeat("\n",substr_count($c,"\n")),$data); $data=explode("\n",$data);
- if(!is_array($data) || empty($data)) { echo("ERROR: unable to read file ".$fn."\n"); $data=[]; }
- $var['op']=15; if(!$ha)$var['om']=15; $nop=""; $il=$am=$hp=$hd=$hb=0; $is=[];
- $Is=[1=>8,2=>16,3=>32,4=>32,5=>64,6=>64,7=>64,8=>64];
- foreach($data as $L=>$line) {
- $line=trim($line);
- if(empty($line) || $line[0]=='/') continue;
- if($line[0]=='+') { $copy[]=substr($line,1); continue; }
- $rows=explode("\t",$line);
- $rows[0]=str_replace("{","",$rows[0]);
- if($rows[0][0]=='<') {
- $d=str_replace("}","_opt",str_replace(">","",substr($rows[0],1)));
- if(preg_match("/[^a-zA-Z0-9_]/",$d)) { echo("ERROR: not a valid argument name '".$rows[0]."' in line ".($L+1)."\n"); continue; }
- if(isset($argdef[$d]))
- echo("ERROR: argument type ".$rows[0]." redefined in line ".($L+1)."\n");
- $argdef[$d]=$rows[1]; if(strpos($rows[1],'^')!==false) $hb=1;
- $T=preg_replace("/[^a-zA-Z]/","", preg_replace("/[\"']([^'\"]*)[\"']/","",preg_replace("/[\@\'a-zA-Z][a-zA-Z0-9_]+/","",$rows[1])));
- unset($t); for($i=0;$i<strlen($T);$i++) $t[$T[$i]]=1;
- preg_match_all("/[^a-zA-Z0-9](a[0-9]+)[^a-zA-Z0-9]/"," ".$rows[1]." ",$m);
- if(!empty($m[1])) foreach($m[1] as $k=>$v) $t[$v]=1;
- $argdeft[$d]=!empty($t)?array_keys($t):[];
- continue;
- }
- if($rows[0]=="@disasm") { $pre=trim($rows[1]); continue; }
- if($rows[0][0]=='@') { if(isset($list[substr($rows[0],1)])&&substr($rows[0],1)!="signext") echo("ERROR: list ".$rows[0]." redefined in line ".($L+1)."\n");
- $list[substr($rows[0],1)]=explode(" ",strtolower(trim(@$rows[1]))); continue; }
- if(empty($rows[1]) && substr($rows[0],-1)!='+') { echo("ERROR: missing mnemonics in line ".($L+1)."\n"); continue; }
- $bp=explode("+",$rows[0]);
- if(empty($Is[strlen($bp[0])/8])) { echo("ERROR: bad bitmask length in line ".($L+1)."\n"); continue; }
- if(preg_match("/[^a-zA-Z01]/",$bp[0])) { echo("ERROR: invalid character in bitmask in line ".($L+1)."\n"); continue; }
- $bm=preg_replace("/[^01]/","x",$bp[0]);
- if(empty($in[$bm])) $in[$bm]=(object)[];
- $in[$bm]->l[]=$L+1;
- $in[$bm]->c=$bp[0];
- if(strpos($rows[1],"<c>")) { $listc["conds"]=1; $argdefc["c"]=1; }
- $in[$bm]->i=str_replace("<c>","%s",strtolower($rows[1]));
- $in[$bm]->p=isset($bp[1])&&(empty($bp[1])||$bp[1]==""); if($in[$bm]->p) $hp=1;
- $p=strtolower(str_replace("0","",str_replace("1","",str_replace("x","",$bp[0]))));
- unset($d); for($i=0;$i<strlen($p);$i++) @$d[$p[$i]]++;
- if(!empty($d)) foreach($d as $b=>$v) if(@$var[$b]<$v) $var[$b]=$v;
- if(!empty($rows[3])) {
- $in[$bm]->e=trim($rows[3]); preg_match_all("/([^=;]+)=([^=;]+)/",$in[$bm]->e,$m);
- if(!empty($m)&&!empty($m[1]))
- foreach($m[1] as $k=>$v) { $v=trim($v); @$d[$v]++; if(!isset($var[$v]) && !empty($m[2][$k])) {if(strpos($m[2][$k],"\"")!==false) $varc[$v]=1; else $var[$v]=8; } }
- }
- if(!empty($bp[1])&&$bp[1]!="") { $in[$bm]->d=explode(",",$bp[1]); $hd=1; foreach($in[$bm]->d as $i)
- if(preg_match("/a([0-9]+)/",$i,$m)){
- if(intval($m[1])>=count($in[$bm]->d)) echo("WARNING: opcode argument 'a".$m[1]."' required by another argument not defined in line ".($L+1)."\n");
- else $ar["a".$m[1]]=1;
- }elseif($hv&&preg_match("/^[a-zA-Z][^0-9]/",$i)&&empty($d[$i[0]]))
- echo("WARNING: bits '".$i[0]."' required by opcode argument not defined in bitmask in line ".($L+1)."\n");
- }
- $in[$bm]->a=[]; $c=[];
- if(!empty($rows[2])){
- foreach(explode(",",preg_replace("/^,/","",preg_replace("/,$/","",str_replace(",,offs",",offs",str_replace("offs,,","offs,",
- str_replace(",,offe",",offe",str_replace("offe,,","offe,",str_replace(">","",str_replace("}","_opt",
- str_replace("{","",str_replace(" ","",str_replace("[",isset($argdef["offs"])?",offs,":"",
- str_replace("]",isset($argdef["offe"])?",offe,":"",$rows[2]))))))))))))) as $a) {
- $a=preg_replace("/^[^<]*</","",$a);
- if(empty($a) || trim($a)=="") { unset($in[$bm]); echo("ERROR: mailformed argument list in line ".($L+1)."\n"); continue; }
- $b=str_replace("_opt","",$a);
- if(empty($argdef[$a])) { unset($in[$bm]); echo("ERROR: undefined argument ".($a!=$b?"{":"")."<".
- str_replace("_opt","",$a).">".($a!=$b?"}":"")." in line ".($L+1)."\n"); continue; }
- if(!empty($argdeft[$a])) {
- for($i=0;$i<count($argdeft[$a]);$i++) { $c[$argdeft[$a][$i]]=1;
- if(preg_match("/^a[0-9]+$/",$argdeft[$a][$i])) {
- $ar[$argdeft[$a][$i]]=1; if(intval(substr($argdeft[$a][$i],1))>=count($in[$bm]->d))
- echo("WARNING: opcode argument '".$argdeft[$a][$i]."' required by <".str_replace("_opt","",$a)."> not defined in line ".($L+1)."\n");
- }elseif(empty($d[$argdeft[$a][$i]])&&$a!="offs"&&$a!="offe"&&$hv)
- echo("WARNING: bits '".$argdeft[$a][$i]."' required by <".str_replace("_opt","",$a)."> not defined in bitmask in line ".($L+1)."\n");
- }
- }
- $argdefc[$a]=1; $in[$bm]->a[]=$a;
- }
- }
- if(!empty($in[$bm]->d)&&$hv){ $e=[]; $f=" ".implode(" ",$in[$bm]->d)." ";for($i=0;$i<count($in[$bm]->d);$i++) if(empty($c["a".$i])&&!preg_match("/[^a-z]a".$i."[^a-z0-9]/",$f)) $e[]="a".$i;
- if(!empty($e))echo("WARNING: opcode argument(s) '".implode("','",$e)."' defined but not referenced in line ".($L+1)."\n");}
- if(!empty($d)&&$hv) {$e=[]; unset($d['c']); foreach($d as $k=>$v) if(empty($c[$k])) $e[]=$k;
- if(!empty($e))echo("WARNING: bit(s) '".implode("','",$e)."' defined but not referenced in line ".($L+1)."\n");}
- if(count($in[$bm]->a)>$am) $am=count($in[$bm]->a);
- }
- foreach($in as $c=>$l) { if(count($l->l)>1) die("CRIT: ambiguous bitmasks ".$c." in lines ".implode(", ",$l->l)."\n"); }
- if($hv) foreach($argdef as $k=>$v) if(empty($argdefc[$k])) echo("WARNING: unreferenced argument type <".$k.">\n");
- foreach($argdefc as $k=>$v) { preg_match_all("/@([^\[]+)/",$argdef[$k],$m); if(!empty($m)&&!empty($m[1])) { foreach($m[1] as $M) {
- if(empty($list[$M])) die("ERROR: undefined list @".$M." in <".str_replace("_opt","",$k).">\n"); $listc[$M]=1; } } }
- $listc['signext']=1; if($hv) foreach($list as $k=>$v) if(empty($listc[$k])) echo("WARNING: unreferenced list @".$k."\n");
- $r=[]; foreach($in as $k=>$o) { $d=$o->p."|".(!empty($o->d)?@implode(",",$o->d):"")."|".@$o->e."|".($o->i=="nop"?"1":"0")."|"; if(!empty($o->a)) foreach($o->a as $a) $d.=$a."|"; $r[$d][]=$o->c; }
- foreach($r as $v) { sort($v); unset($V); foreach($v as $i) $V[preg_replace("/[01]/","}",$i)][]=$i; foreach($V as $k=>$v) { $s=0;
- do{
- $e=count($v); do { $c=[]; for($i=0;$i<strlen($k);$i++) { if($k[$i]!='}') continue; $c[$i]=[0,0]; for($j=$s;$j<$e;$j++) $c[$i][intval($v[$j][$i])]++; } $d=0; foreach($c as $a) if($a[0]!=0&&$a[1]!=0) $d++; $e--; } while($e>$s && pow(2,ceil(log($e-$s)/log(2))+1)<(1<<$d)); $e++;
- $g=array_slice($v,$s,$e-$s);
- $c=[]; for($i=0;$i<strlen($k);$i++) { if($k[$i]!='}') continue; $c[$i]=[0,0]; for($j=$s;$j<$e;$j++) $c[$i][intval($v[$j][$i])]++; }
- $d=""; $b=0; for($i=0;$i<strlen($k);$i++) { if($k[$i]!='}') { $d.=$k[$i]; continue; } $c=[0,0];
- for($j=$s;$j<$e;$j++) $c[intval($v[$j][$i])]++; $d.=$c[0]==0?'1':($c[1]==0?'0':'~'); if($c[0]!=0&&$c[1]!=0) $b++; }
- $o=preg_replace("/[^01]/","x",$g[0]); $n=preg_replace("/[^01]/","x",$d);
- if(isset($out[$n])) die("CRIT: conflicting bitmask ".$d."\n"); if(empty($out[$n])) $out[$n]=(object)[]; @$out[$n]->bm=$d; $out[$n]->c=str_replace("x","0",$n);
- $out[$n]->m=str_replace("x","0",str_replace("0","1",$n)); $out[$n]->s=strlen($d); $is[$out[$n]->s]=$out[$n]->s/8; $out[$n]->i=[];
- for($i=0;$i<strlen($d);$i++) if($d[$i]!='X'&&preg_match("/[A-Z~]/",$d[$i])) $out[$n]->b[$d[$i]!='~'?strtolower($d[$i]):"op"][]=(strlen($n)-1-$i);
- for($i=0;$i<strlen($d);$i++) if($d[$i]!='x'&&preg_match("/[a-z]/",$d[$i])) $out[$n]->b[$d[$i]][]=(strlen($n)-1-$i);
- foreach(['p','d','e','a'] as $a) if(isset($in[$o]->$a)) $out[$n]->$a=$in[$o]->$a;
- for($i=0;$i<pow(2,$b);$i++) {
- $a=$b-1;$c="";for($j=0;$j<strlen($d);$j++) if($d[$j]=='~') { $c.=($i&(1<<$a)?'1':'0'); $a--; } else $c.=$d[$j];
- @$m=$in[preg_replace("/[^01]/","x",$c)]->i; if($m) { if($m=="nop") $nop=$n; $mn[$m]=1; if(strlen($m)>$il) $il=strlen($m); }
- $out[$n]->i[]=$m?$m:"?";
- }
- for($i=count($out[$n]->i)-1;$i>0;$i--) if($out[$n]->i[$i]=="?") unset($out[$n]->i[$i]); else break;
- $s=$e;
- } while($s<count($v));
- }
- }
- ksort($out,SORT_STRING);
- echo("STAT: Lists: ".count($list).", Argument types: ".count($argdefc).", Longest mnemonic: ".$il.", Max arguments: ".$am."\n");
- echo("STAT: Mnemonics: ".count($mn).", Instruction groups: ".count($out).", Instructions: ".count($in)."\n");
- if($il<7) $il=7; if(empty($is)) $is[8]=1;
- foreach($var as $k=>$v) { if($v<=8) $var[$k]=8; else if($v<=16) $var[$k]=16; else if($var[$k]<=32) $var[$k]=32; else $var[$k]=64; }
- $sho=[];
- foreach($out as $k=>$o) {
- if(!empty($o->b)) foreach($o->b as $g=>$b) {
- $c=[];$l=count($b);foreach($b as $K=>$A) @$c[$A-($l-$K-1)]|=1<<($l-$K-1);
- foreach($c as $v=>$b) if($v) @$sho[$o->s."_".$v]++;
- }
- if(str_replace("0","",$o->m)==$o->m && $Is[$o->s/8]==strlen($o->m)) continue;
- $w=0; foreach([24,16,8] as $i) if(substr($o->m,-$i)==str_repeat("0",$i)) { $w=$i;break; }
- if($w>0) @$sho[$o->s."_".$w]++;
- }
- foreach($sho as $k=>$v) if($v<3) unset($sho[$k]);
- $c="/* Universal Disassembler Function Library\n * https://gitlab.com/bztsrc/udisasm\n *\n * ----- GENERATED FILE, DO NOT EDIT! -----\n *\n * Copyright (C) 2017 bzt (bztsrc@gitlab)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the \"Software\"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * @brief Disassembler source generated from ".$fn."
- */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
- $c.="#define ".$pre."_arch \"".explode(".",$fn)[0]."\"\n";
- if($hn) $c.="#define ".$pre."_snprintf 1\n";
- if($ha) $c.="#define ".$pre."_analytics 1\n";
- if($hi) $c.="#define ".$pre."_integration 1\nextern uint8_t sys_fault;\nextern uint64_t dbg_label, buf_reloc;\n";
- $c.="enum { ".$pre."_arg_NONE,".$pre."_arg_ofs,".$pre."_arg_ofe"; foreach($argdefc as $k=>$v) $c.=", ".$pre."_arg_".$k; $c.=" };\n";
- $c.="\n/*** private functions ***/\n";
- $c.="char *".$pre."_str(char*s,int n) {";
- //due to a gcc optimizer bug when compiling to Aarch64, we have to remove the extra checks... F*ck
- //$c.="while(s&&*((uint16_t*)s)&&n){s++;if(!*s){s++;n--;}}return s&&*s?s:\"?\";";
- $c.="if(!s)return \"?\";while(n){s++;if(!*s){s++;n--;}}return *s?s:\"?\";";
- $c.="}\n";foreach($copy as $C) $c.=str_replace("disasm_",$pre."_",$C)."\n";
- $c.="\n/*** public API ***/\nuint64_t ".$pre."(uint64_t addr, char *str".($hn?", int size":"").")\n{\n";
- foreach([64,32,16,8] as $i) {
- $o=0;foreach($var as $k=>$v)if($v==$i){$o=1;break;}if(!$o)continue;
- $c.=" uint".$i."_t "; $f=1; foreach($var as $k=>$v) { if($v==$i) { if($f) $f=0; else $c.=", "; $c.=$k."=0";} }
- $c.=";\n";
- }
- if($hd) $c.=" int64_t ".implode(", ",array_keys($ar)).";\n";
- foreach($is as $i=>$v) {
- $c.=" uint".($Is[$i/8])."_t ic".$i;
- foreach($sho as $j=>$v) if(explode("_",$j)[0]==$i) $c.=", ic".$j;
- $c.=";\n";
- }
- if($ha) $c.=" uint64_t oaddr=addr;\n uint8_t ai;\n";
- if($hp||$hb) $c.=" uint64_t iaddr=addr".($hi?"-buf_reloc":"").";\n";
- $c.=" char *names=NULL".($ha?",psb[256],*ps=(char*)&psb":",*olds=str").($hn?",*ends=str+size-".($ha?"5":"3"):"");
- if(!empty($varc)) foreach($varc as $k=>$v) $c.=",*".$k."=NULL"; $c.=";\n";
- foreach($list as $k=>$v) if($k!="disasm"&&$k!="signext") { $c.=" char *".$k."=\""; foreach($v as $t) $c.=$t."\\0"; $c.="\";\n"; }
- $c.=" uint8_t args[".($am+1)."]={0".str_repeat(",0",$am)."};\n\n";
- if($hp) $c.="getopcode:\n";
- if($hi) $c.=" dbg_label=0; sys_fault=0;\n";
- foreach($is as $i=>$v)
- $c.=" ic".$i."=*((uint".($Is[$i/8])."_t*)addr);\n";
- if(!empty($sho)){$c.=" ";foreach($sho as $i=>$v) $c.=" ic".$i."=ic".str_replace("_",">>",$i).";";$c.="\n";}
- if($hi) $c.=" if(sys_fault) return addr+1;\n";
- if(isset($out[$nop])) {
- $c.="\n /* handle multiple NOPs at once */\n if(ic".$out[$nop]->s."==0x".b2h($out[$nop]->c).
- ") {\n while(*((uint".$out[$nop]->s."_t*)addr)==ic".$out[$nop]->s.") { op++; addr+=".($out[$nop]->s/8)."; }\n".
- " if(str!=NULL) ";
- if($ha) {
- $c.="str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"size,":"")."\"{\\\"mask\\\":\\\"".$out[$nop]->bm."\\\",\\\"prefix\\\":[],\\\"instruction\\\":[";
- $d=dechex(bindec($out[$nop]->c)); for($i=strlen($d)-2;$i>=0;$i-=2) $c.="0x".substr($d,$i,2).($i?", ":"");
- $c.="],\\\"count\\\":%d,\\\"bitgroups\\\":{},\\\"arguments\\\":[],\\\"prefixstr\\\":\\\"\\\",\\\"decoded\\\":\\\"nop\\\"}\",op);";
- } else
- $c.="str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"size,":"")."\" %d x nop\",op);";
- $c.="\n *str=0;\n return addr;\n }\n";
- }
- $c.="\n /* decode instruction */\n"; $e=0;
- foreach($out as $k=>$o) {
- if($k==$nop) continue;
- if($o->m==$o->c&&intval($o->m)==0) { $c.=" "; $e=1; } else {
- $c.=" if(";
- if(str_replace("0","",$o->m)==$o->m && $Is[$o->s/8]==strlen($o->m)) $c.="ic".$Is[$o->s/8]."==0x".b2h($o->c); else {
- $w=0; foreach([24,16,8] as $i) if(substr($o->m,-$i)==str_repeat("0",$i)) { $w=$i;break; }
- $c.="(".($w?"(":"")."ic".$o->s.(isset($sho[$o->s."_".$w])?"_".$w.")":($w?">>".$w.")":"")).
- "&0x".b2h(substr($o->m,0,strlen($o->m)-$w)).")==0x".b2h(substr($o->c,0,strlen($o->c)-$w));
- } $c.=") "; } $c.="{\n";
- if(!empty($o->i) && $o->i[0]!="") $c.=" names=\"";foreach($o->i as $i) $c.=$i."\\0";$c.="\";\n";
- if(!empty($o->b)) {$c.=" ";foreach($o->b as $k=>$v) {if($hp)$c.=$k."<<=".count($v).";"; $c.=$k."=".sh($v,in_array($k,$list['signext']),$o->s,$sho)."; ";} $c.="\n";}
- if(!empty($o->e)) $c.=" ".$o->e.";\n";
- if(!empty($o->a)) {$c.=" "; foreach($o->a as $k=>$a) $c.="args[".$k."]=".$pre."_arg_".$a."; ";$c.="\n";}
- if($ha && empty($o->p)) {
- $c.=" if(str!=NULL) {\n";
- $c.=" str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"{\\\"mask\\\":\\\"".$o->bm."\\\",\\\"prefix\\\":[\");\n";
- $c.=" ai=0;for(;oaddr<addr;oaddr++){str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"%s0x%02x\",ai?\", \":\"\", *((uint8_t*)oaddr)); ai=1; }\n";
- $c.=" str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"],\\\"instruction\\\":[\");\n";
- if(count($is)!=1) $c.=" }\n";
- }
- if(count($is)!=1) $c.=" addr+=".($o->s/8).";\n";
- if($ha && empty($o->p)) {
- if(count($is)!=1) $c.=" if(str!=NULL) {\n";
- $c.=" for(ai=0;ai<".($o->s/8).";ai++) str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"%s0x%02x\",ai?\",\":\"\", *((uint8_t*)(oaddr+ai)));\n";
- $c.=" str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"],\\\"count\\\":1,\\\"bitgroups\\\":{";
- if(!empty($o->b)) { $d=0;foreach($o->b as $k=>$v) {$c.=($d?", ":"")."\\\"".($k=="op"?"~":$k)."\\\":%d";$d=1;} $c.="\""; foreach($o->b as $k=>$v) $c.=",".$k; } else $c.="\"";
- $c.=");\n str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"},\\\"arguments\\\":[\");\n";
- }
- if(!empty($o->d)) { foreach($o->d as $k=>$i) {
- $c.=" ";
- if(preg_match("/^[0-9]+$/",$i)) $c.="a".$k."=(int64_t)(*((int".($Is[$i])."_t*)addr));".(isset($list['signext']['a'.$k])?" a".$k."|=(a".$k.">>".($i*8-1).")&1?-1L<<".($i*8).":0;":"");
- $c.="addr+=".$i.";\n"; }
- if($hi) $c.=" if(sys_fault) { *str=0; return addr; }\n";}
- if($ha && empty($o->p)) {
- if(count($is)!=1) $c.=" if(str!=NULL) {\n";
- if(!empty($o->d)) {
- $d=0; foreach($o->d as $k=>$i) {
- $c.=" ".($d?"*str++=',';":"")."*str++='[';";
- $c.=" for(ai=0;ai<".$i.";ai++) str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"%s0x%x\",ai?\",\":\"\",*((uint8_t*)oaddr++));\n";
- $c.=" *str++=']';".($hn?"if(str>=ends) return 0;":"")."\n";
- $d=1;
- }
- }
- $c.=" *ps=0; str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"],\\\"prefixstr\\\":\\\"%s\\\",\\\"decoded\\\":\\\"\",psb);\n";
- $c.=" }\n";
- }
- if($o->p) { if(!empty($o->i) && $o->i[0]!="") $c.=" if(str!=NULL) ".($ha?"ps":"str").($hs?"":"+")."=s".($hn?"n":"")."printf(".($ha?"ps":"str").($hn?",".($ha?"256":"ends-str"):"").",\"%s \",".$pre."_str(names,op));\n";
- $c.=" iaddr=addr".($hi?"-buf_reloc":"")."; goto getopcode;\n"; }
- $c.=" }".(!$e?" else":"")."\n";
- }
- if(!$e) $c.=" names=NULL;\n";
- $c.="\n if(str!=NULL) {\n str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"").$pre."_str(names,op)".(isset($var['c'])&&isset($list['conds'])?",".$pre."_str(conds,c)":"").");\n";
- if($hn) $c.=" if(str>=ends) return 0;\n";
- if($ha) $c.=" *str++=' ';\n";
- else $c.=" if(str-olds<".($il+1).")om=".($il+1)."-(str-olds);else om=1;for(op=0;op<om;op++) *str++=' ';\n";
- $c.=" for(op=0;op<sizeof(args) && args[op]!=".$pre."_arg_NONE;op++) {\n";
- if($hn) $c.=" if(str>=ends) return 0;\n";
- $c.=" if(op".(isset($argdefc["offs"])?"&&args[op-1]!=".$pre."_arg_offs":"").(isset($argdefc["offe"])?"&&args[op]!=".$pre."_arg_offe":"").") { *str++=','; *str++=' '; }\n";
- $c.=" switch(args[op]) {\n";
- foreach($argdefc as $k=>$v) {
- $c.=" case ".$pre."_arg_".$k.": str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"");
- $d=str_replace('^',"(int)iaddr",str_replace('$',"((int)addr".(count($is)==1?"+".reset($is):"").")",str_replace("disasm_",$pre."_",$argdef[$k])));
- if(strpos($d,"@")!==false) {
- $d=preg_replace("/@([^\[]+)\[([^\]]+)\]/",$pre.'_str($1,$2)',$d);
- $c.="\"%s\", ".$d;
- } else $c.=$d;
- $c.="); "; if($hi&&substr($k,0,5)=="label")$c.="dbg_label=".trim(preg_replace("/^[^,]*,?/","",$d)).";"; $c.="break;\n";
- }
- $c.=" default: break;\n }\n if(*(str-2)==',')str-=2;\n";
- $c.=" }\n";
- if($ha)
- $c.=" str".($hs?"":"+")."=s".($hn?"n":"")."printf(str,".($hn?"ends-str,":"")."\"\\\"}\");\n";
- $c.=" *str=0;\n }\n return ".($hn?"str>=ends?0:":"")."addr".(count($is)==1?"+".reset($is):"").";\n}\n\n";
- $c.="#ifdef __cplusplus\n}\n#endif\n\n";
- $fn=explode(".",$fn)[0].".h";file_put_contents($fn,$c); echo("DONE: C header ".$fn." saved.\n");
|