| 1 | \r |
| 2 | // Dave's Disa 68000 Disassembler\r |
| 3 | #ifndef __GNUC__\r |
| 4 | #pragma warning(disable:4115)\r |
| 5 | #endif\r |
| 6 | #include <stdio.h>\r |
| 7 | #include <string.h>\r |
| 8 | #include "Disa.h"\r |
| 9 | \r |
| 10 | unsigned int DisaPc=0;\r |
| 11 | char *DisaText=NULL; // Text buffer to write in\r |
| 12 | static char Tasm[]="bwl?";\r |
| 13 | static char Comment[64]="";\r |
| 14 | unsigned short (CPU_CALL *DisaWord)(unsigned int a)=NULL;\r |
| 15 | \r |
| 16 | static unsigned int DisaLong(unsigned int a)\r |
| 17 | {\r |
| 18 | unsigned int d=0;\r |
| 19 | if (DisaWord==NULL) return d;\r |
| 20 | \r |
| 21 | d= DisaWord(a)<<16;\r |
| 22 | d|=DisaWord(a+2)&0xffff;\r |
| 23 | return d;\r |
| 24 | }\r |
| 25 | \r |
| 26 | // Get text version of the effective address\r |
| 27 | int DisaGetEa(char *t,int ea,int size)\r |
| 28 | {\r |
| 29 | ea&=0x3f; t[0]=0;\r |
| 30 | if ((ea&0x38)==0x00) { sprintf(t,"d%d",ea ); return 0; } // 000rrr\r |
| 31 | if ((ea&0x38)==0x08) { sprintf(t,"a%d",ea&7); return 0; } // 001rrr\r |
| 32 | if ((ea&0x38)==0x10) { sprintf(t,"(a%d)",ea&7); return 0; } // 010rrr\r |
| 33 | if ((ea&0x38)==0x18) { sprintf(t,"(a%d)+",ea&7); return 0; } // 011rrr\r |
| 34 | if ((ea&0x38)==0x20) { sprintf(t,"-(a%d)",ea&7); return 0; } // 100rrr\r |
| 35 | if ((ea&0x38)==0x28) { sprintf(t,"($%x,a%d)",DisaWord(DisaPc)&0xffff,ea&7); DisaPc+=2; return 0; } // 101rrr\r |
| 36 | \r |
| 37 | if ((ea&0x38)==0x30)\r |
| 38 | {\r |
| 39 | // 110nnn - An + Disp + D/An\r |
| 40 | int areg=0,ext=0,off=0,da=0,reg=0,wol=0,scale=0;\r |
| 41 | ext=DisaWord(DisaPc)&0xffff;\r |
| 42 | \r |
| 43 | areg=ea&7;\r |
| 44 | off=ext&0xff; da =ext&0x8000?'a':'d';\r |
| 45 | reg=(ext>>12)&7; wol=ext&0x0800?'l':'w';\r |
| 46 | scale=1<<((ext>>9)&3);\r |
| 47 | \r |
| 48 | if (scale<2) sprintf(t,"($%x,a%d,%c%d.%c)", off,areg,da,reg,wol);\r |
| 49 | else sprintf(t,"($%x,a%d,%c%d.%c*%d)",off,areg,da,reg,wol,scale); // 68020\r |
| 50 | \r |
| 51 | DisaPc+=2;\r |
| 52 | return 0;\r |
| 53 | }\r |
| 54 | \r |
| 55 | if (ea==0x38) { sprintf(t,"$%x.w",DisaWord(DisaPc)&0xffff); DisaPc+=2; return 0; } // 111000 - Absolute short\r |
| 56 | if (ea==0x39) { sprintf(t,"$%x.l",DisaLong(DisaPc)); DisaPc+=4; return 0; } // 111001 - Absolute long\r |
| 57 | \r |
| 58 | if (ea==0x3a)\r |
| 59 | {\r |
| 60 | // 111010 - PC Relative\r |
| 61 | int ext=DisaWord(DisaPc)&0xffff;\r |
| 62 | sprintf(t,"($%x,pc)",ext);\r |
| 63 | sprintf(Comment,"; =%x",DisaPc+(short)ext); // Comment where pc+ext is\r |
| 64 | DisaPc+=2;\r |
| 65 | return 0;\r |
| 66 | }\r |
| 67 | \r |
| 68 | if (ea==0x3b)\r |
| 69 | {\r |
| 70 | // 111011 - PC Relative + D/An\r |
| 71 | int ext=0,off=0,da=0,reg=0,wol=0,scale=0;\r |
| 72 | ext=DisaWord(DisaPc)&0xffff;\r |
| 73 | \r |
| 74 | off=ext&0xff; da =ext&0x8000?'a':'d';\r |
| 75 | reg=(ext>>12)&7; wol=ext&0x0800?'l':'w';\r |
| 76 | scale=1<<((ext>>9)&3);\r |
| 77 | \r |
| 78 | if (scale<2) sprintf(t,"($%x,pc,%c%d.%c)", off,da,reg,wol);\r |
| 79 | else sprintf(t,"($%x,pc,%c%d.%c*%d)",off,da,reg,wol,scale); // 68020\r |
| 80 | \r |
| 81 | sprintf(Comment,"; =%x",DisaPc+(char)off); // Comment where pc+ext is\r |
| 82 | DisaPc+=2;\r |
| 83 | return 0;\r |
| 84 | }\r |
| 85 | \r |
| 86 | if (ea==0x3c)\r |
| 87 | {\r |
| 88 | // 111100 - Immediate\r |
| 89 | switch (size)\r |
| 90 | {\r |
| 91 | case 0: sprintf(t,"#$%x",DisaWord(DisaPc)&0x00ff); DisaPc+=2; return 0;\r |
| 92 | case 1: sprintf(t,"#$%x",DisaWord(DisaPc)&0xffff); DisaPc+=2; return 0;\r |
| 93 | case 2: sprintf(t,"#$%x",DisaLong(DisaPc) ); DisaPc+=4; return 0;\r |
| 94 | }\r |
| 95 | return 1;\r |
| 96 | }\r |
| 97 | \r |
| 98 | // Unknown effective address\r |
| 99 | sprintf(t,"ea=(%d%d%d %d%d%d)",\r |
| 100 | (ea>>5)&1,(ea>>4)&1,(ea>>3)&1,\r |
| 101 | (ea>>2)&1,(ea>>1)&1, ea &1);\r |
| 102 | return 1;\r |
| 103 | }\r |
| 104 | \r |
| 105 | static void GetOffset(char *text)\r |
| 106 | {\r |
| 107 | int off=(short)DisaWord(DisaPc); DisaPc+=2;\r |
| 108 | \r |
| 109 | if (off<0) sprintf(text,"-$%x",-off);\r |
| 110 | else sprintf(text,"$%x", off);\r |
| 111 | }\r |
| 112 | \r |
| 113 | // ================ Opcodes 0x0000+ ================\r |
| 114 | static int DisaArithImm(int op)\r |
| 115 | {\r |
| 116 | // Or/And/Sub/Add/Eor/Cmp Immediate 0000ttt0 xxDDDddd (tt=type, xx=size extension, DDDddd=Dest ea)\r |
| 117 | int dea=0;\r |
| 118 | char seat[64]="",deat[64]="";\r |
| 119 | int type=0,size=0;\r |
| 120 | char *arith[8]={"or","and","sub","add","?","eor","cmp","?"};\r |
| 121 | \r |
| 122 | type=(op>>9)&7; if (type==4 || type>=7) return 1;\r |
| 123 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 124 | dea=op&0x3f; if (dea==0x3c) return 1;\r |
| 125 | \r |
| 126 | DisaGetEa(seat,0x3c,size);\r |
| 127 | DisaGetEa(deat,dea, size);\r |
| 128 | \r |
| 129 | sprintf(DisaText,"%si.%c %s, %s",arith[type],Tasm[size],seat,deat);\r |
| 130 | return 0;\r |
| 131 | }\r |
| 132 | \r |
| 133 | // ================ Opcodes 0x0108+ ================\r |
| 134 | static int DisaMovep(int op)\r |
| 135 | {\r |
| 136 | // movep.x (Aa),Dn - 0000nnn1 dx001aaa nn\r |
| 137 | int dn=0,dir=0,size=0,an=0;\r |
| 138 | char offset[32]="";\r |
| 139 | \r |
| 140 | dn =(op>>9)&7;\r |
| 141 | dir =(op>>7)&1;\r |
| 142 | size=(op>>6)&1; size++;\r |
| 143 | an = op &7;\r |
| 144 | \r |
| 145 | GetOffset(offset);\r |
| 146 | if (dir) sprintf(DisaText,"movep.%c d%d, (%s,a%d)",Tasm[size],dn,offset,an);\r |
| 147 | else sprintf(DisaText,"movep.%c (%s,a%d), d%d",Tasm[size],offset,an,dn);\r |
| 148 | \r |
| 149 | return 0;\r |
| 150 | }\r |
| 151 | \r |
| 152 | // ================ Opcodes 0x007c+ ================\r |
| 153 | static int DisaArithSr(int op)\r |
| 154 | {\r |
| 155 | // Ori/Andi/Eori $nnnn,sr 0000t0tx 0s111100\r |
| 156 | char *opcode[6]={"ori","andi","","","","eori"};\r |
| 157 | char seat[64]="";\r |
| 158 | int type=0,size=0;\r |
| 159 | \r |
| 160 | type=(op>>9)&5;\r |
| 161 | size=(op>>6)&1;\r |
| 162 | \r |
| 163 | DisaGetEa(seat,0x3c,size);\r |
| 164 | sprintf(DisaText,"%s.%c %s, %s", opcode[type], Tasm[size], seat, size?"sr":"ccr");\r |
| 165 | \r |
| 166 | return 0;\r |
| 167 | }\r |
| 168 | \r |
| 169 | // ================ Opcodes 0x0100+ ================\r |
| 170 | static int DisaBtstReg(int op)\r |
| 171 | {\r |
| 172 | // Btst/Bchg/Bclr/Bset 0000nnn1 tteeeeee (nn=reg number, eeeeee=Dest ea)\r |
| 173 | int type=0;\r |
| 174 | int sea=0,dea=0;\r |
| 175 | char seat[64]="",deat[64]="";\r |
| 176 | char *opcode[4]={"btst","bchg","bclr","bset"};\r |
| 177 | \r |
| 178 | sea =(op>>9)&7;\r |
| 179 | type=(op>>6)&3;\r |
| 180 | dea= op&0x3f;\r |
| 181 | \r |
| 182 | if ((dea&0x38)==0x08) return 1; // movep\r |
| 183 | DisaGetEa(seat,sea,0);\r |
| 184 | DisaGetEa(deat,dea,0);\r |
| 185 | \r |
| 186 | sprintf(DisaText,"%s %s, %s",opcode[type],seat,deat);\r |
| 187 | return 0;\r |
| 188 | }\r |
| 189 | \r |
| 190 | // ================ Opcodes 0x0800+ ================\r |
| 191 | static int DisaBtstImm(int op)\r |
| 192 | {\r |
| 193 | // Btst/Bchg/Bclr/Bset 00001000 tteeeeee 00 nn (eeeeee=ea, nn=bit number)\r |
| 194 | int type=0;\r |
| 195 | char seat[64]="",deat[64]="";\r |
| 196 | char *opcode[4]={"btst","bchg","bclr","bset"};\r |
| 197 | \r |
| 198 | type=(op>>6)&3;\r |
| 199 | DisaGetEa(seat, 0x3c,0);\r |
| 200 | DisaGetEa(deat,op&0x3f,0);\r |
| 201 | \r |
| 202 | sprintf(DisaText,"%s %s, %s",opcode[type],seat,deat);\r |
| 203 | return 0;\r |
| 204 | }\r |
| 205 | \r |
| 206 | // ================ Opcodes 0x1000+ ================\r |
| 207 | static int DisaMove(int op)\r |
| 208 | {\r |
| 209 | // Move 00xxdddD DDssssss (xx=size extension, ssssss=Source EA, DDDddd=Dest ea)\r |
| 210 | int sea=0,dea=0;\r |
| 211 | char inst[64]="",seat[64]="",deat[64]="";\r |
| 212 | char *movea="";\r |
| 213 | int size=0;\r |
| 214 | \r |
| 215 | if ((op&0x01c0)==0x0040) movea="a"; // See if it's a movea opcode\r |
| 216 | \r |
| 217 | // Find size extension\r |
| 218 | switch (op&0x3000)\r |
| 219 | {\r |
| 220 | case 0x1000: size=0; break;\r |
| 221 | case 0x3000: size=1; break;\r |
| 222 | case 0x2000: size=2; break;\r |
| 223 | default: return 1;\r |
| 224 | }\r |
| 225 | \r |
| 226 | sea = op&0x003f;\r |
| 227 | DisaGetEa(seat,sea,size);\r |
| 228 | \r |
| 229 | dea =(op&0x01c0)>>3;\r |
| 230 | dea|=(op&0x0e00)>>9;\r |
| 231 | DisaGetEa(deat,dea,size);\r |
| 232 | \r |
| 233 | sprintf(inst,"move%s.%c",movea,Tasm[size]);\r |
| 234 | sprintf(DisaText,"%s %s, %s",inst,seat,deat);\r |
| 235 | return 0;\r |
| 236 | }\r |
| 237 | \r |
| 238 | // ================ Opcodes 0x4000+ ================\r |
| 239 | static int DisaNeg(int op)\r |
| 240 | {\r |
| 241 | // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA)\r |
| 242 | char eat[64]="";\r |
| 243 | int type=0,size=0;\r |
| 244 | char *opcode[4]={"negx","clr","neg","not"};\r |
| 245 | \r |
| 246 | type=(op>>9)&3;\r |
| 247 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 248 | DisaGetEa(eat,op&0x3f,size);\r |
| 249 | \r |
| 250 | sprintf(DisaText,"%s.%c %s",opcode[type],Tasm[size],eat);\r |
| 251 | return 0;\r |
| 252 | }\r |
| 253 | \r |
| 254 | // ================ Opcodes 0x40c0+ ================\r |
| 255 | static int DisaMoveSr(int op)\r |
| 256 | {\r |
| 257 | // 01000tt0 11eeeeee (tt=type, xx=size, eeeeee=EA)\r |
| 258 | int type=0,ea=0;\r |
| 259 | char eat[64]="";\r |
| 260 | \r |
| 261 | type=(op>>9)&3;\r |
| 262 | ea=op&0x3f;\r |
| 263 | DisaGetEa(eat,ea,1);\r |
| 264 | \r |
| 265 | switch (type)\r |
| 266 | {\r |
| 267 | default: sprintf(DisaText,"move sr, %s", eat); break;\r |
| 268 | case 1: sprintf(DisaText,"move ccr, %s",eat); break;\r |
| 269 | case 2: sprintf(DisaText,"move %s, ccr",eat); break;\r |
| 270 | case 3: sprintf(DisaText,"move %s, sr", eat); break;\r |
| 271 | }\r |
| 272 | return 0;\r |
| 273 | }\r |
| 274 | \r |
| 275 | static int OpChk(int op)\r |
| 276 | {\r |
| 277 | int sea=0,dea=0;\r |
| 278 | char seat[64]="",deat[64]="";\r |
| 279 | \r |
| 280 | sea=op&0x003f;\r |
| 281 | DisaGetEa(seat,sea,0);\r |
| 282 | \r |
| 283 | dea=(op>>9)&7; dea|=8;\r |
| 284 | DisaGetEa(deat,dea,2);\r |
| 285 | \r |
| 286 | sprintf(DisaText,"chk %s, %s",seat,deat);\r |
| 287 | return 0;\r |
| 288 | }\r |
| 289 | \r |
| 290 | // ================ Opcodes 0x41c0+ ================\r |
| 291 | static int DisaLea(int op)\r |
| 292 | {\r |
| 293 | // Lea 0100nnn1 11eeeeee (eeeeee=ea)\r |
| 294 | int sea=0,dea=0;\r |
| 295 | char seat[64]="",deat[64]="";\r |
| 296 | \r |
| 297 | sea=op&0x003f;\r |
| 298 | DisaGetEa(seat,sea,0);\r |
| 299 | \r |
| 300 | dea=(op>>9)&7; dea|=8;\r |
| 301 | DisaGetEa(deat,dea,2);\r |
| 302 | \r |
| 303 | sprintf(DisaText,"lea %s, %s",seat,deat);\r |
| 304 | return 0;\r |
| 305 | }\r |
| 306 | \r |
| 307 | static int MakeRegList(char *list,int mask,int ea)\r |
| 308 | {\r |
| 309 | int reverse=0,i=0,low=0,len=0;\r |
| 310 | \r |
| 311 | if ((ea&0x38)==0x20) reverse=1; // -(An), bitfield is reversed\r |
| 312 | \r |
| 313 | mask&=0xffff; list[0]=0;\r |
| 314 | \r |
| 315 | for (i=0;i<17;i++)\r |
| 316 | {\r |
| 317 | int bit=0;\r |
| 318 | \r |
| 319 | // Mask off bit i:\r |
| 320 | if (reverse) bit=0x8000>>i; else bit=1<<i;\r |
| 321 | bit&=mask;\r |
| 322 | \r |
| 323 | if (bit==0 || i==8)\r |
| 324 | {\r |
| 325 | // low to i-1 are a continuous section, add it:\r |
| 326 | char add[16]="";\r |
| 327 | int ad=low&8?'a':'d';\r |
| 328 | if (low==i-1) sprintf(add,"%c%d/", ad,low&7);\r |
| 329 | if (low< i-1) sprintf(add,"%c%d-%c%d/",ad,low&7, ad,(i-1)&7);\r |
| 330 | strcat(list,add);\r |
| 331 | \r |
| 332 | low=i; // Next section\r |
| 333 | }\r |
| 334 | \r |
| 335 | if (bit==0) low=i+1;\r |
| 336 | }\r |
| 337 | \r |
| 338 | // Knock off trailing '/'\r |
| 339 | len=strlen(list);\r |
| 340 | if (len>0) if (list[len-1]=='/') list[len-1]=0;\r |
| 341 | return 0;\r |
| 342 | }\r |
| 343 | \r |
| 344 | // ================ Opcodes 0x4800+ ================\r |
| 345 | static int DisaNbcd(int op)\r |
| 346 | {\r |
| 347 | // Nbcd 01001000 00eeeeee (eeeeee=ea)\r |
| 348 | int ea=0;\r |
| 349 | char eat[64]="";\r |
| 350 | \r |
| 351 | ea=op&0x003f;\r |
| 352 | DisaGetEa(eat,ea,0);\r |
| 353 | \r |
| 354 | sprintf(DisaText,"nbcd %s",eat);\r |
| 355 | return 0;\r |
| 356 | }\r |
| 357 | \r |
| 358 | // ================ Opcodes 0x4840+ ================\r |
| 359 | static int DisaSwap(int op)\r |
| 360 | {\r |
| 361 | // Swap, 01001000 01000nnn swap Dn\r |
| 362 | sprintf(DisaText,"swap d%d",op&7);\r |
| 363 | return 0;\r |
| 364 | }\r |
| 365 | \r |
| 366 | // ================ Opcodes 0x4850+ ================\r |
| 367 | static int DisaPea(int op)\r |
| 368 | {\r |
| 369 | // Pea 01001000 01eeeeee (eeeeee=ea) pea\r |
| 370 | int ea=0;\r |
| 371 | char eat[64]="";\r |
| 372 | \r |
| 373 | ea=op&0x003f; if (ea<0x10) return 1; // swap opcode\r |
| 374 | DisaGetEa(eat,ea,2);\r |
| 375 | \r |
| 376 | sprintf(DisaText,"pea %s",eat);\r |
| 377 | return 0;\r |
| 378 | }\r |
| 379 | \r |
| 380 | // ================ Opcodes 0x4880+ ================\r |
| 381 | static int DisaExt(int op)\r |
| 382 | {\r |
| 383 | // Ext 01001000 1x000nnn (x=size, eeeeee=EA)\r |
| 384 | char eat[64]="";\r |
| 385 | int size=0;\r |
| 386 | \r |
| 387 | size=(op>>6)&1; size++;\r |
| 388 | DisaGetEa(eat,op&0x3f,size);\r |
| 389 | \r |
| 390 | sprintf(DisaText,"ext.%c %s",Tasm[size],eat);\r |
| 391 | return 0;\r |
| 392 | }\r |
| 393 | \r |
| 394 | // ================ Opcodes 0x4890+ ================\r |
| 395 | static int DisaMovem(int op)\r |
| 396 | {\r |
| 397 | // Movem 01001d00 1xeeeeee regmask d=direction, x=size, eeeeee=EA\r |
| 398 | int dir=0,size=0;\r |
| 399 | int ea=0,mask=0;\r |
| 400 | char list[64]="",eat[64]="";\r |
| 401 | \r |
| 402 | dir=(op>>10)&1;\r |
| 403 | size=((op>>6)&1)+1;\r |
| 404 | ea=op&0x3f; if (ea<0x10) return 1; // ext opcode\r |
| 405 | \r |
| 406 | mask=DisaWord(DisaPc)&0xffff; DisaPc+=2;\r |
| 407 | \r |
| 408 | MakeRegList(list,mask,ea); // Turn register mask into text\r |
| 409 | DisaGetEa(eat,ea,size);\r |
| 410 | \r |
| 411 | if (dir) sprintf(DisaText,"movem.%c %s, %s",Tasm[size],eat,list);\r |
| 412 | else sprintf(DisaText,"movem.%c %s, %s",Tasm[size],list,eat);\r |
| 413 | return 0;\r |
| 414 | }\r |
| 415 | \r |
| 416 | // ================ Opcodes 0x4e40+ ================\r |
| 417 | static int DisaTrap(int op)\r |
| 418 | {\r |
| 419 | sprintf(DisaText,"trap #%d",op&0xf);\r |
| 420 | return 0;\r |
| 421 | }\r |
| 422 | \r |
| 423 | // ================ Opcodes 0x4e50+ ================\r |
| 424 | static int DisaLink(int op)\r |
| 425 | {\r |
| 426 | // Link opcode, 01001110 01010nnn dd link An,#offset\r |
| 427 | char eat[64]="";\r |
| 428 | char offset[32]="";\r |
| 429 | \r |
| 430 | DisaGetEa(eat,(op&7)|8,0);\r |
| 431 | GetOffset(offset);\r |
| 432 | \r |
| 433 | sprintf(DisaText,"link %s,#%s",eat,offset);\r |
| 434 | \r |
| 435 | return 0;\r |
| 436 | }\r |
| 437 | \r |
| 438 | // ================ Opcodes 0x4e58+ ================\r |
| 439 | static int DisaUnlk(int op)\r |
| 440 | {\r |
| 441 | // Link opcode, 01001110 01011nnn dd unlk An\r |
| 442 | char eat[64]="";\r |
| 443 | \r |
| 444 | DisaGetEa(eat,(op&7)|8,0);\r |
| 445 | sprintf(DisaText,"unlk %s",eat);\r |
| 446 | \r |
| 447 | return 0;\r |
| 448 | }\r |
| 449 | \r |
| 450 | // ================ Opcodes 0x4e60+ ================\r |
| 451 | static int DisaMoveUsp(int op)\r |
| 452 | {\r |
| 453 | // Move USP opcode, 01001110 0110dnnn move An to/from USP (d=direction)\r |
| 454 | int ea=0,dir=0;\r |
| 455 | char eat[64]="";\r |
| 456 | \r |
| 457 | dir=(op>>3)&1;\r |
| 458 | ea=(op&7)|8;\r |
| 459 | DisaGetEa(eat,ea,0);\r |
| 460 | \r |
| 461 | if (dir) sprintf(DisaText,"move usp, %s",eat);\r |
| 462 | else sprintf(DisaText,"move %s, usp",eat);\r |
| 463 | return 0;\r |
| 464 | }\r |
| 465 | \r |
| 466 | // ================ Opcodes 0x4e70+ ================\r |
| 467 | static int Disa4E70(int op)\r |
| 468 | {\r |
| 469 | char *inst[8]={"reset","nop","stop","rte","rtd","rts","trapv","rtr"};\r |
| 470 | int n=0;\r |
| 471 | \r |
| 472 | n=op&7;\r |
| 473 | \r |
| 474 | sprintf(DisaText,"%s",inst[n]);\r |
| 475 | \r |
| 476 | //todo - 'stop' with 16 bit data\r |
| 477 | \r |
| 478 | return 0;\r |
| 479 | }\r |
| 480 | \r |
| 481 | // ================ Opcodes 0x4a00+ ================\r |
| 482 | static int DisaTst(int op)\r |
| 483 | {\r |
| 484 | // Tst 01001010 xxeeeeee (eeeeee=ea)\r |
| 485 | int ea=0;\r |
| 486 | char eat[64]="";\r |
| 487 | int size=0;\r |
| 488 | \r |
| 489 | ea=op&0x003f;\r |
| 490 | DisaGetEa(eat,ea,0);\r |
| 491 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 492 | \r |
| 493 | sprintf(DisaText,"tst.%c %s",Tasm[size],eat);\r |
| 494 | return 0;\r |
| 495 | }\r |
| 496 | \r |
| 497 | static int DisaTas(int op)\r |
| 498 | {\r |
| 499 | // Tas 01001010 11eeeeee (eeeeee=ea)\r |
| 500 | int ea=0;\r |
| 501 | char eat[64]="";\r |
| 502 | \r |
| 503 | ea=op&0x003f;\r |
| 504 | DisaGetEa(eat,ea,0);\r |
| 505 | \r |
| 506 | sprintf(DisaText,"tas %s",eat);\r |
| 507 | return 0;\r |
| 508 | }\r |
| 509 | \r |
| 510 | // ================ Opcodes 0x4e80+ ================\r |
| 511 | static int DisaJsr(int op)\r |
| 512 | {\r |
| 513 | // Jsr/Jmp 0100 1110 1mEE Eeee (eeeeee=ea m=1=jmp)\r |
| 514 | int sea=0;\r |
| 515 | char seat[64]="";\r |
| 516 | \r |
| 517 | sea=op&0x003f;\r |
| 518 | DisaGetEa(seat,sea,0);\r |
| 519 | \r |
| 520 | sprintf(DisaText,"j%s %s", op&0x40?"mp":"sr", seat);\r |
| 521 | return 0;\r |
| 522 | }\r |
| 523 | \r |
| 524 | // ================ Opcodes 0x5000+ ================\r |
| 525 | static int DisaAddq(int op)\r |
| 526 | {\r |
| 527 | // 0101nnnt xxeeeeee (nnn=#8,1-7 t=addq/subq xx=size, eeeeee=EA)\r |
| 528 | int num=0,type=0,size=0,ea=0;\r |
| 529 | char eat[64]="";\r |
| 530 | \r |
| 531 | num =(op>>9)&7; if (num==0) num=8;\r |
| 532 | type=(op>>8)&1;\r |
| 533 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 534 | ea = op&0x3f;\r |
| 535 | \r |
| 536 | DisaGetEa(eat,ea,size);\r |
| 537 | \r |
| 538 | sprintf(DisaText,"%s.%c #%d, %s",type?"subq":"addq",Tasm[size],num,eat);\r |
| 539 | return 0;\r |
| 540 | }\r |
| 541 | \r |
| 542 | // ================ Opcodes 0x50c0+ ================\r |
| 543 | static int DisaSet(int op)\r |
| 544 | {\r |
| 545 | // 0101cccc 11eeeeee (sxx ea)\r |
| 546 | static char *cond[16]=\r |
| 547 | {"t" ,"f", "hi","ls","cc","cs","ne","eq",\r |
| 548 | "vc","vs","pl","mi","ge","lt","gt","le"};\r |
| 549 | char *cc="";\r |
| 550 | int ea=0;\r |
| 551 | char eat[64]="";\r |
| 552 | \r |
| 553 | cc=cond[(op>>8)&0xf]; // Get condition code\r |
| 554 | ea=op&0x3f;\r |
| 555 | if ((ea&0x38)==0x08) return 1; // dbra, not scc\r |
| 556 | \r |
| 557 | DisaGetEa(eat,ea,0);\r |
| 558 | sprintf(DisaText,"s%s %s",cc,eat);\r |
| 559 | return 0;\r |
| 560 | }\r |
| 561 | \r |
| 562 | // ================ Opcodes 0x50c8+ ================\r |
| 563 | static int DisaDbra(int op)\r |
| 564 | {\r |
| 565 | // 0101cccc 11001nnn offset (dbra/dbxx Rn,offset)\r |
| 566 | int dea=0; char deat[64]="";\r |
| 567 | int pc=0,Offset=0;\r |
| 568 | \r |
| 569 | static char *BraCode[16]=\r |
| 570 | {"bt" ,"bra","bhi","bls","bcc","bcs","bne","beq",\r |
| 571 | "bvc","bvs","bpl","bmi","bge","blt","bgt","ble"};\r |
| 572 | char *Bra="";\r |
| 573 | \r |
| 574 | dea=op&7;\r |
| 575 | DisaGetEa(deat,dea,2);\r |
| 576 | \r |
| 577 | // Get condition code\r |
| 578 | Bra=BraCode[(op>>8)&0xf];\r |
| 579 | \r |
| 580 | // Get offset\r |
| 581 | pc=DisaPc;\r |
| 582 | Offset=(short)DisaWord(DisaPc); DisaPc+=2;\r |
| 583 | \r |
| 584 | sprintf(DisaText,"d%s %s, %x",Bra,deat,pc+Offset);\r |
| 585 | return 0;\r |
| 586 | }\r |
| 587 | \r |
| 588 | // ================ Opcodes 0x6000+ ================\r |
| 589 | static int DisaBranch(int op)\r |
| 590 | {\r |
| 591 | // Branch 0110cccc nn (cccc=condition)\r |
| 592 | int pc=0,Offset=0;\r |
| 593 | \r |
| 594 | static char *BraCode[16]=\r |
| 595 | {"bra","bsr","bhi","bls","bcc","bcs","bne","beq",\r |
| 596 | "bvc","bvs","bpl","bmi","bge","blt","bgt","ble"};\r |
| 597 | char *Bra="";\r |
| 598 | \r |
| 599 | // Get condition code\r |
| 600 | Bra=BraCode[(op>>8)&0x0f];\r |
| 601 | \r |
| 602 | // Get offset\r |
| 603 | pc=DisaPc;\r |
| 604 | Offset=(char)(op&0xff);\r |
| 605 | if (Offset== 0) { Offset=(short)DisaWord(DisaPc); DisaPc+=2; }\r |
| 606 | else if (Offset==-1) { Offset= DisaLong(DisaPc); DisaPc+=4; }\r |
| 607 | \r |
| 608 | sprintf(DisaText,"%s %x",Bra,pc+Offset);\r |
| 609 | return 0;\r |
| 610 | }\r |
| 611 | \r |
| 612 | // ================ Opcodes 0x7000+ ================\r |
| 613 | static int DisaMoveq(int op)\r |
| 614 | {\r |
| 615 | // Moveq 0111rrr0 nn (rrr=Dest register, nn=data)\r |
| 616 | \r |
| 617 | int dea=0; char deat[64]="";\r |
| 618 | char *inst="moveq";\r |
| 619 | int val=0;\r |
| 620 | \r |
| 621 | dea=(op>>9)&7;\r |
| 622 | DisaGetEa(deat,dea,2);\r |
| 623 | \r |
| 624 | val=(char)(op&0xff);\r |
| 625 | sprintf(DisaText,"%s #$%x, %s",inst,val,deat);\r |
| 626 | return 0;\r |
| 627 | }\r |
| 628 | \r |
| 629 | // ================ Opcodes 0x8000+ ================\r |
| 630 | static int DisaArithReg(int op)\r |
| 631 | {\r |
| 632 | // 1t0tnnnd xxeeeeee (tt=type:or/sub/and/add xx=size, eeeeee=EA)\r |
| 633 | int type=0,size=0,dir=0,rea=0,ea=0;\r |
| 634 | char reat[64]="",eat[64]="";\r |
| 635 | char *opcode[]={"or","sub","","","and","add"};\r |
| 636 | \r |
| 637 | type=(op>>12)&5;\r |
| 638 | rea =(op>> 9)&7;\r |
| 639 | dir =(op>> 8)&1;\r |
| 640 | size=(op>> 6)&3; if (size>=3) return 1;\r |
| 641 | ea = op&0x3f;\r |
| 642 | \r |
| 643 | if (dir && ea<0x10) return 1; // addx opcode\r |
| 644 | \r |
| 645 | DisaGetEa(reat,rea,size);\r |
| 646 | DisaGetEa( eat, ea,size);\r |
| 647 | \r |
| 648 | if (dir) sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],reat,eat);\r |
| 649 | else sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],eat,reat);\r |
| 650 | return 0;\r |
| 651 | }\r |
| 652 | \r |
| 653 | // ================ Opcodes 0x8100+ ================\r |
| 654 | static int DisaAbcd(int op)\r |
| 655 | {\r |
| 656 | // 1t00ddd1 0000asss - sbcd/abcd Ds,Dd or -(As),-(Ad)\r |
| 657 | int type=0;\r |
| 658 | int dn=0,addr=0,sn=0;\r |
| 659 | char *opcode[]={"sbcd","abcd"};\r |
| 660 | \r |
| 661 | type=(op>>14)&1;\r |
| 662 | dn =(op>> 9)&7;\r |
| 663 | addr=(op>> 3)&1;\r |
| 664 | sn = op &7;\r |
| 665 | \r |
| 666 | if (addr) sprintf(DisaText,"%s -(a%d), -(a%d)",opcode[type],sn,dn);\r |
| 667 | else sprintf(DisaText,"%s d%d, d%d", opcode[type],sn,dn);\r |
| 668 | \r |
| 669 | return 0;\r |
| 670 | }\r |
| 671 | \r |
| 672 | // ================ Opcodes 0x80c0+ ================\r |
| 673 | static int DisaMul(int op)\r |
| 674 | {\r |
| 675 | // Div/Mul: 1m00nnns 11eeeeee (m=Mul, nnn=Register Dn, s=signed, eeeeee=EA)\r |
| 676 | int type=0,rea=0,sign=0,ea=0,size=1;\r |
| 677 | char reat[64]="",eat[64]="";\r |
| 678 | char *opcode[2]={"div","mul"};\r |
| 679 | \r |
| 680 | type=(op>>14)&1; // div/mul\r |
| 681 | rea =(op>> 9)&7;\r |
| 682 | sign=(op>> 8)&1;\r |
| 683 | ea = op&0x3f;\r |
| 684 | \r |
| 685 | DisaGetEa(reat,rea,size);\r |
| 686 | DisaGetEa( eat, ea,size);\r |
| 687 | \r |
| 688 | sprintf(DisaText,"%s%c.%c %s, %s",opcode[type],sign?'s':'u',Tasm[size],eat,reat);\r |
| 689 | return 0;\r |
| 690 | }\r |
| 691 | \r |
| 692 | // ================ Opcodes 0x90c0+ ================\r |
| 693 | static int DisaAritha(int op)\r |
| 694 | {\r |
| 695 | // Suba/Cmpa/Adda 1tt1nnnx 11eeeeee (tt=type, x=size, eeeeee=Source EA)\r |
| 696 | int type=0,size=0,sea=0,dea=0;\r |
| 697 | char seat[64]="",deat[64]="";\r |
| 698 | char *aritha[4]={"suba","cmpa","adda",""};\r |
| 699 | \r |
| 700 | type=(op>>13)&3; if (type>=3) return 1;\r |
| 701 | size=(op>>8)&1; size++;\r |
| 702 | dea =(op>>9)&7; dea|=8; // Dest=An\r |
| 703 | sea = op&0x003f; // Source\r |
| 704 | \r |
| 705 | DisaGetEa(seat,sea,size);\r |
| 706 | DisaGetEa(deat,dea,size);\r |
| 707 | \r |
| 708 | sprintf(DisaText,"%s.%c %s, %s",aritha[type],Tasm[size],seat,deat);\r |
| 709 | return 0;\r |
| 710 | }\r |
| 711 | \r |
| 712 | // ================ Opcodes 0xb000+ ================\r |
| 713 | static int DisaCmpEor(int op)\r |
| 714 | {\r |
| 715 | // Cmp/Eor 1011rrrt xxeeeeee (rrr=Dn, t=cmp/eor, xx=size extension, eeeeee=ea)\r |
| 716 | char reat[64]="",eat[64]="";\r |
| 717 | int type=0,size=0;\r |
| 718 | \r |
| 719 | type=(op>>8)&1;\r |
| 720 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 721 | DisaGetEa(reat,(op>>9)&7,size);\r |
| 722 | DisaGetEa(eat, op&0x3f, size);\r |
| 723 | \r |
| 724 | if (type) sprintf(DisaText,"eor.%c %s, %s",Tasm[size],reat,eat);\r |
| 725 | else sprintf(DisaText,"cmp.%c %s, %s",Tasm[size],eat,reat);\r |
| 726 | return 0;\r |
| 727 | }\r |
| 728 | \r |
| 729 | static int DisaCmpm(int op)\r |
| 730 | {\r |
| 731 | char seat[64]="",deat[64]="";\r |
| 732 | int type=0,size=0,sea,dea;\r |
| 733 | \r |
| 734 | type=(op>>8)&1;\r |
| 735 | size=(op>>6)&3; if (size>=3) return 1;\r |
| 736 | sea=(op&7)|0x18;\r |
| 737 | dea=(op>>9)&0x3f;\r |
| 738 | DisaGetEa(seat,sea,size);\r |
| 739 | DisaGetEa(deat,dea,size);\r |
| 740 | \r |
| 741 | sprintf(DisaText,"cmpm.%c %s, %s",Tasm[size],seat,deat);\r |
| 742 | return 0;\r |
| 743 | }\r |
| 744 | \r |
| 745 | \r |
| 746 | // ================ Opcodes 0xc140+ ================\r |
| 747 | // 1100ttt1 01000sss exg ds,dt\r |
| 748 | // 1100ttt1 01001sss exg as,at\r |
| 749 | // 1100ttt1 10001sss exg as,dt\r |
| 750 | static int DisaExg(int op)\r |
| 751 | {\r |
| 752 | int tr=0,type=0,sr=0;\r |
| 753 | \r |
| 754 | tr =(op>>9)&7;\r |
| 755 | type= op&0xf8;\r |
| 756 | sr = op&7;\r |
| 757 | \r |
| 758 | if (type==0x40) sprintf(DisaText,"exg d%d, d%d",sr,tr);\r |
| 759 | else if (type==0x48) sprintf(DisaText,"exg a%d, a%d",sr,tr);\r |
| 760 | else if (type==0x88) sprintf(DisaText,"exg a%d, d%d",sr,tr);\r |
| 761 | else return 1;\r |
| 762 | \r |
| 763 | return 0;\r |
| 764 | }\r |
| 765 | \r |
| 766 | // ================ Opcodes 0xd100+ ================\r |
| 767 | static int DisaAddx(int op)\r |
| 768 | {\r |
| 769 | // 1t01ddd1 xx000sss addx\r |
| 770 | int type=0,size=0,dea=0,sea=0,mem;\r |
| 771 | char deat[64]="",seat[64]="";\r |
| 772 | char *opcode[6]={"","subx","","","","addx"};\r |
| 773 | \r |
| 774 | type=(op>>12)&5;\r |
| 775 | dea =(op>> 9)&7;\r |
| 776 | size=(op>> 6)&3; if (size>=3) return 1;\r |
| 777 | sea = op&7;\r |
| 778 | mem = op&8;\r |
| 779 | if(mem) { sea+=0x20; dea+=0x20; }\r |
| 780 | \r |
| 781 | DisaGetEa(deat,dea,size);\r |
| 782 | DisaGetEa(seat,sea,size);\r |
| 783 | \r |
| 784 | sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],seat,deat);\r |
| 785 | return 0;\r |
| 786 | }\r |
| 787 | \r |
| 788 | // ================ Opcodes 0xe000+ ================\r |
| 789 | static char *AsrName[4]={"as","ls","rox","ro"};\r |
| 790 | static int DisaAsr(int op)\r |
| 791 | {\r |
| 792 | // Asr/l/Ror/l etc - 1110cccd xxuttnnn\r |
| 793 | // (ccc=count, d=direction xx=size extension, u=use reg for count, tt=type, nnn=register Dn)\r |
| 794 | int count=0,dir=0,size=0,usereg=0,type=0,num=0;\r |
| 795 | \r |
| 796 | count =(op>>9)&7;\r |
| 797 | dir =(op>>8)&1;\r |
| 798 | size =(op>>6)&3; if (size>=3) return 1; // todo Asr EA\r |
| 799 | usereg=(op>>5)&1;\r |
| 800 | type =(op>>3)&3;\r |
| 801 | num = op &7; // Register number\r |
| 802 | \r |
| 803 | if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8\r |
| 804 | \r |
| 805 | sprintf(DisaText,"%s%c.%c %c%d, d%d",\r |
| 806 | AsrName[type], dir?'l':'r', Tasm[size],\r |
| 807 | usereg?'d':'#', count, num);\r |
| 808 | return 0;\r |
| 809 | }\r |
| 810 | \r |
| 811 | static int DisaAsrEa(int op)\r |
| 812 | {\r |
| 813 | // Asr/l/Ror/l etc EA - 11100ttd 11eeeeee\r |
| 814 | int type=0,dir=0,size=1;\r |
| 815 | char eat[64]="";\r |
| 816 | \r |
| 817 | type=(op>>9)&3;\r |
| 818 | dir =(op>>8)&1;\r |
| 819 | DisaGetEa(eat,op&0x3f,size);\r |
| 820 | \r |
| 821 | sprintf(DisaText,"%s%c.w %s", AsrName[type], dir?'l':'r', eat);\r |
| 822 | return 0;\r |
| 823 | }\r |
| 824 | \r |
| 825 | // =================================================================\r |
| 826 | \r |
| 827 | static int TryOp(int op)\r |
| 828 | {\r |
| 829 | if ((op&0xf100)==0x0000) DisaArithImm(op); // Ori/And/Sub/Add/Eor/Cmp Immediate\r |
| 830 | if ((op&0xf5bf)==0x003c) DisaArithSr(op); // Ori/Andi/Eori $nnnn,sr\r |
| 831 | if ((op&0xf100)==0x0100) DisaBtstReg(op);\r |
| 832 | if ((op&0xf138)==0x0108) DisaMovep(op);\r |
| 833 | if ((op&0xff00)==0x0800) DisaBtstImm(op); // Btst/Bchg/Bclr/Bset\r |
| 834 | if ((op&0xc000)==0x0000) DisaMove(op);\r |
| 835 | if ((op&0xf900)==0x4000) DisaNeg(op); // Negx/Clr/Neg/Not\r |
| 836 | if ((op&0xf140)==0x4100) OpChk(op);\r |
| 837 | if ((op&0xf1c0)==0x41c0) DisaLea(op);\r |
| 838 | if ((op&0xf9c0)==0x40c0) DisaMoveSr(op);\r |
| 839 | if ((op&0xffc0)==0x4800) DisaNbcd(op);\r |
| 840 | if ((op&0xfff8)==0x4840) DisaSwap(op);\r |
| 841 | if ((op&0xffc0)==0x4840) DisaPea(op);\r |
| 842 | if ((op&0xffb8)==0x4880) DisaExt(op);\r |
| 843 | if ((op&0xfb80)==0x4880) DisaMovem(op);\r |
| 844 | if ((op&0xff00)==0x4a00) DisaTst(op);\r |
| 845 | if ((op&0xffc0)==0x4ac0) DisaTas(op);\r |
| 846 | if ((op&0xfff0)==0x4e40) DisaTrap(op);\r |
| 847 | if ((op&0xfff8)==0x4e50) DisaLink(op);\r |
| 848 | if ((op&0xfff8)==0x4e58) DisaUnlk(op);\r |
| 849 | if ((op&0xfff0)==0x4e60) DisaMoveUsp(op);\r |
| 850 | if ((op&0xfff8)==0x4e70) Disa4E70(op);\r |
| 851 | if ((op&0xff80)==0x4e80) DisaJsr(op);\r |
| 852 | if ((op&0xf000)==0x5000) DisaAddq(op);\r |
| 853 | if ((op&0xf0c0)==0x50c0) DisaSet(op);\r |
| 854 | if ((op&0xf0f8)==0x50c8) DisaDbra(op);\r |
| 855 | if ((op&0xf000)==0x6000) DisaBranch(op);\r |
| 856 | if ((op&0xa000)==0x8000) DisaArithReg(op); // Or/Sub/And/Add\r |
| 857 | if ((op&0xb1f0)==0x8100) DisaAbcd(op);\r |
| 858 | if ((op&0xb130)==0x9100) DisaAddx(op);\r |
| 859 | if ((op&0xb0c0)==0x80c0) DisaMul(op);\r |
| 860 | if ((op&0xf100)==0x7000) DisaMoveq(op);\r |
| 861 | if ((op&0x90c0)==0x90c0) DisaAritha(op);\r |
| 862 | if ((op&0xf000)==0xb000) DisaCmpEor(op);\r |
| 863 | if ((op&0xf138)==0xb108) DisaCmpm(op);\r |
| 864 | if ((op&0xf130)==0xc100) DisaExg(op);\r |
| 865 | if ((op&0xf000)==0xe000) DisaAsr(op);\r |
| 866 | if ((op&0xf8c0)==0xe0c0) DisaAsrEa(op);\r |
| 867 | \r |
| 868 | // Unknown opcoode\r |
| 869 | return 0;\r |
| 870 | }\r |
| 871 | \r |
| 872 | int DisaGet()\r |
| 873 | {\r |
| 874 | int op=0;\r |
| 875 | if (DisaWord==NULL) return 1;\r |
| 876 | \r |
| 877 | Comment[0]=0;\r |
| 878 | DisaText[0]=0; // Assume opcode unknown\r |
| 879 | \r |
| 880 | op=DisaWord(DisaPc)&0xffff; DisaPc+=2;\r |
| 881 | TryOp(op);\r |
| 882 | strcat(DisaText,Comment);\r |
| 883 | \r |
| 884 | // Unknown opcoode\r |
| 885 | return 0;\r |
| 886 | }\r |