Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

alphadis.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      alphadis.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "alphadis.h"
00022 #include "alphaopc.h"
00023 #include "htdebug.h"
00024 #include "tools.h"
00025 
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #define BITS_OPC(opcode)                ((opcode >> 26) & 0x3f)
00030 #define BITS_FFUN(opcode)       ((opcode >> 5)  & 0x7ff)
00031 #define BITS_IFUN(opcode)       ((opcode >> 5)  & 0x7f)
00032 #define BITS_MFUN(opcode)       (opcode  & 0xffff)
00033 #define BITS_JFUN(opcode)       ((opcode >> 14) & 0x3)
00034 #define BITS_ISLIT(opcode)      ((opcode >> 12) & 0x1)
00035 #define BITS_IMMED(opcode)      ((opcode >> 13) & 0xff)
00036 #define BITS_REGA(opcode)       ((opcode >> 21) & 0x1f)
00037 #define BITS_REGB(opcode)       ((opcode >> 16) & 0x1f)
00038 #define BITS_REGC(opcode)       (opcode & 0x1f)
00039 #define BITS_BDISP(opcode)      (opcode & 0x1fffff)
00040 #define BITS_BSIGN(opcode)      (opcode & 0x100000)
00041 #define BITS_MDISP(opcode)      (opcode & 0xffff)
00042 #define BITS_MSIGN(opcode)      (opcode & 0x8000)
00043 #define BITS_PAL(opcode)                (opcode & 0x3ffffff)
00044 #define BITS_HINT(opcode)       (opcode & 0x3fff)
00045 
00046 /* only needed for assembler.. */
00047 #define MAKE_OPC(opcode)                ((opcode & 0x3f) << 26)
00048 #define MAKE_FFUN(opcode)       ((opcode & 0x7ff) << 5)
00049 #define MAKE_IFUN(opcode)       ((opcode & 0x7f) << 5)
00050 #define MAKE_MFUN(opcode)       (opcode & 0xffff)
00051 #define MAKE_JFUN(opcode)       ((opcode & 0x3) << 14)
00052 #define MAKE_LIT                        (1<<12)
00053 #define MAKE_IMMED(opcode)      ((opcode & 0xff)  << 13 )
00054 #define MAKE_REGA(opcode)       ((opcode & 0x1f) << 21)
00055 #define MAKE_REGB(opcode)       ((opcode & 0x1f) << 16)
00056 #define MAKE_REGC(opcode)       (opcode & 0x1f)
00057 #define MAKE_BDISP(opcode)      (opcode & 0x1fffff)
00058 #define MAKE_MDISP(opcode)      (opcode & 0xffff)
00059 #define MAKE_PAL(opcode)                (opcode & 0x3ffffff)
00060 #define MAKE_HINT(opcode)       (opcode & 0x3fff)
00061 
00062 Alphadis::Alphadis():Disassembler()
00063 {
00064         insn.valid = false;
00065 }
00066 
00067 Alphadis::~Alphadis()
00068 {
00069 }
00070 
00071 int Alphadis::load(ht_object_stream *f)
00072 {
00073         return Disassembler::load(f);
00074 }
00075 
00076 int find_alpha_instruction(alpha_opcode_tab_entry *table, int f)
00077 {
00078         int i=0;
00079         while (f > (table+i)->fcode) i++;
00080         return i;
00081 }
00082 
00083 dis_insn *Alphadis::decode(byte *code, int maxlen, CPU_ADDR addr)
00084 {
00085         // alpha code instructions must be 32 bits long
00086         if (maxlen < 4) {
00087                 // invalid
00088                 insn.valid = false;
00089                 insn.size = maxlen;
00090                 insn.table = 0;
00091                 // FIXME: this reads to much bytes!
00092                 UNALIGNED_MOVE(insn.data, *(dword *)code);
00093         } else {
00094                 insn.valid = true;
00095                 insn.size = 4;
00096                 insn.table = &alpha_instr_tbl[0];
00097                 dword opcode = *((dword *)code);
00098                 int idx = BITS_OPC(opcode);
00099                 switch (alpha_instr_tbl[idx].type) {
00100                         case ALPHA_EXTENSION_10:
00101                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext10[0], BITS_IFUN(opcode));
00102                                 insn.table = &alpha_instr_tbl_ext10[0];
00103                                 break;
00104                         case ALPHA_EXTENSION_11:
00105                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext11[0], BITS_IFUN(opcode));
00106                                 insn.table = &alpha_instr_tbl_ext11[0];
00107                                 break;
00108                         case ALPHA_EXTENSION_12:
00109                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext12[0], BITS_IFUN(opcode));
00110                                 insn.table = &alpha_instr_tbl_ext12[0];
00111                                 break;
00112                         case ALPHA_EXTENSION_13:
00113                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext13[0], BITS_IFUN(opcode));
00114                                 insn.table = &alpha_instr_tbl_ext13[0];
00115                                 break;
00116                         case ALPHA_EXTENSION_14:
00117                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext14[0], BITS_FFUN(opcode));
00118                                 insn.table = &alpha_instr_tbl_ext14[0];
00119                                 break;
00120                         case ALPHA_EXTENSION_15:
00121                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext15[0], BITS_FFUN(opcode));
00122                                 insn.table = &alpha_instr_tbl_ext15[0];
00123                                 break;
00124                         case ALPHA_EXTENSION_16:
00125                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext16[0], BITS_FFUN(opcode));
00126                                 insn.table = &alpha_instr_tbl_ext16[0];
00127                                 break;
00128                         case ALPHA_EXTENSION_17:
00129                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext17[0], BITS_FFUN(opcode));
00130                                 insn.table = &alpha_instr_tbl_ext17[0];
00131                                 break;
00132                         case ALPHA_EXTENSION_18:
00133                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext18[0], BITS_MFUN(opcode));
00134                                 insn.table = &alpha_instr_tbl_ext18[0];
00135                                 break;
00136                         case ALPHA_EXTENSION_1A:
00137                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext1a[0], BITS_JFUN(opcode));
00138                                 insn.table = &alpha_instr_tbl_ext1a[0];
00139                                 break;
00140                         case ALPHA_EXTENSION_1C:
00141                                 idx = find_alpha_instruction(&alpha_instr_tbl_ext1c[0], BITS_IFUN(opcode));
00142                                 insn.table = &alpha_instr_tbl_ext1c[0];
00143                                 break;
00144                 }
00145 
00146                 insn.code = idx;
00147 
00148                 switch ((insn.table+idx)->type) {
00149                         case ALPHA_GROUP1:
00150                                 insn.regA = BITS_REGA(opcode);
00151                                 insn.regC = BITS_REGC(opcode);
00152                                 if (BITS_ISLIT(opcode)) {
00153                                         insn.regB = REG_LIT;
00154                                         insn.data = BITS_IMMED(opcode);
00155                                 } else {
00156                                         insn.regB = BITS_REGB(opcode);
00157                                         insn.data = 0;
00158                                 }
00159                                 break;
00160                         case ALPHA_GROUP2:
00161                                 insn.regA = BITS_REGA(opcode) + REG_FLOAT;
00162                                 insn.regB = BITS_REGB(opcode) + REG_FLOAT;
00163                                 insn.regC = BITS_REGC(opcode) + REG_FLOAT;
00164                                 insn.data = 0;
00165                                 break;
00166                         case ALPHA_GROUP3:
00167                                 insn.regA = BITS_REGA(opcode);
00168                                 insn.regB = BITS_REGB(opcode);
00169                                 insn.regC = REG_ZERO;
00170                                 insn.data = BITS_MDISP(opcode);
00171                                 if (BITS_MSIGN(insn.data)) insn.data |= -1 ^ 0xffff;
00172                                 break;
00173                         case ALPHA_GROUP_FLD:
00174                                 insn.regA = BITS_REGA(opcode) + REG_FLOAT;
00175                                 insn.regB = BITS_REGB(opcode);
00176                                 insn.regC = REG_ZERO;
00177                                 insn.data = BITS_MDISP(opcode);
00178                                 if (BITS_MSIGN(insn.data)) insn.data |= -1 ^ 0xffff;
00179                                 break;
00180                         case ALPHA_GROUP4:
00181                                 insn.regA = BITS_REGA(opcode);
00182                                 insn.regB = BITS_REGB(opcode);
00183                                 insn.regC = REG_ZERO;
00184                                 insn.data = BITS_MDISP(opcode);
00185                                 if (BITS_MSIGN(insn.data)) insn.data |= -1 ^ 0xffff;
00186                                 break;
00187                         case ALPHA_GROUP_FST:
00188                                 insn.regA = BITS_REGA(opcode) + REG_FLOAT;
00189                                 insn.regB = BITS_REGB(opcode);
00190                                 insn.regC = REG_ZERO;
00191                                 insn.data = BITS_MDISP(opcode);
00192                                 if (BITS_MSIGN(insn.data)) insn.data |= -1 ^ 0xffff;
00193                                 break;
00194                         case ALPHA_GROUP_F2I:
00195                                 insn.regA = BITS_REGA(opcode) + REG_FLOAT;
00196                                 insn.regB = REG_ZERO;
00197                                 insn.regC = BITS_REGC(opcode);
00198                                 insn.data = 0;
00199                                 break;
00200                         case ALPHA_GROUP_I2F:
00201                                 insn.regA = BITS_REGA(opcode);
00202                                 insn.regB = REG_ZERO;
00203                                 insn.regC = BITS_REGC(opcode) + REG_FLOAT;
00204                                 insn.data = 0;
00205                                 break;
00206                         case ALPHA_GROUP_BRA:
00207                                 insn.regA = BITS_REGA(opcode);
00208                                 insn.regB = REG_ZERO;
00209                                 insn.regC = REG_ZERO;
00210                                 insn.data = BITS_BDISP(opcode);
00211                                 if (BITS_BSIGN(insn.data)) insn.data |= -1 ^ 0x1fffff;
00212                                 insn.data += 1;
00213                                 insn.data *= 4;
00214                                 insn.data += addr.addr32.offset;
00215                                 break;
00216                         case ALPHA_GROUP_FBR:
00217                                 insn.regA = BITS_REGA(opcode) + REG_FLOAT;
00218                                 insn.regB = REG_ZERO;
00219                                 insn.regC = REG_ZERO;
00220                                 insn.data = BITS_BDISP(opcode);
00221                                 if (BITS_BSIGN(insn.data)) insn.data |= -1 ^ 0x1fffff;
00222                                 insn.data += 1;
00223                                 insn.data *= 4;
00224                                 insn.data += addr.addr32.offset;
00225                                 break;
00226                         case ALPHA_GROUP_JMP:
00227                                 insn.regA = BITS_REGA(opcode);
00228                                 insn.regB = BITS_REGB(opcode);
00229                                 insn.regC = REG_ZERO;
00230                                 insn.data = BITS_HINT(opcode);
00231                                 break;
00232                         case ALPHA_GROUP_PAL:
00233                                 insn.regA = REG_ZERO;
00234                                 insn.regB = REG_ZERO;
00235                                 insn.regC = REG_ZERO;
00236                                 insn.data = BITS_PAL(opcode);
00237                                 break;
00238                         default:
00239                                 insn.valid = false;
00240                                 insn.data = *(dword *)code;
00241                                 break;
00242                 }
00243         }
00244         return &insn;
00245 }
00246 
00247 dis_insn *Alphadis::duplicateInsn(dis_insn *disasm_insn)
00248 {
00249         alphadis_insn *insn = (alphadis_insn *)malloc(sizeof (alphadis_insn));
00250         *insn = *(alphadis_insn *)disasm_insn;
00251         return insn;
00252 }
00253 
00254 void Alphadis::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
00255 {
00256         min_length = 4;
00257         max_length = 4;
00258         min_look_ahead = 4;
00259         avg_look_ahead = 4;
00260         addr_align = 4;
00261 }
00262 
00263 char *Alphadis::getName()
00264 {
00265         return "alpha/disassembler";
00266 }
00267 
00268 byte    Alphadis::getSize(dis_insn *disasm_insn)
00269 {
00270         return ((alphadis_insn*)disasm_insn)->size;
00271 }
00272 
00273 OBJECT_ID Alphadis::object_id() const
00274 {
00275         return ATOM_DISASM_ALPHA;
00276 }
00277 
00278 void    Alphadis::store(ht_object_stream *f)
00279 {
00280         Disassembler::store(f);
00281 }
00282 
00283 char    *Alphadis::str(dis_insn *disasm_insn, int style)
00284 {
00285         return strf(disasm_insn, style, "");
00286 }
00287 
00288 #define A_REG_A alpha_reg_names[alpha_insn->regA]
00289 #define A_REG_B alpha_reg_names[alpha_insn->regB]
00290 #define A_REG_C alpha_reg_names[alpha_insn->regC]
00291 #define A_NAME (alpha_insn->table+alpha_insn->code)->name
00292 
00293 char    *Alphadis::strf(dis_insn *disasm_insn, int style, char *format)
00294 {
00295         if (style & DIS_STYLE_HIGHLIGHT) enable_highlighting();
00296         
00297         const char *cs_default = get_cs(e_cs_default);
00298         const char *cs_number = get_cs(e_cs_number);
00299         const char *cs_symbol = get_cs(e_cs_symbol);
00300 
00301         alphadis_insn *alpha_insn = (alphadis_insn *) disasm_insn;
00302         
00303         if (!alpha_insn->valid) {
00304                 is_invalid:
00305                 switch (alpha_insn->size) {
00306                         case 1:
00307                                 strcpy(insnstr, "db         ?");
00308                                 break;
00309                         case 2:
00310                                 strcpy(insnstr, "dw         ?");
00311                                 break;
00312                         case 3:
00313                                 strcpy(insnstr, "db         ? * 3");
00314                                 break;
00315                         case 4:
00316                                 sprintf(insnstr, "dd         %s0x%08lx", cs_number, alpha_insn->data);
00317                                 break;
00318                         default: { /* braces for empty assert */
00319                                 assert(0);
00320                         }
00321                 }
00322         } else switch ((alpha_insn->table+alpha_insn->code)->type) {
00323                 case ALPHA_GROUP1:
00324                 case ALPHA_GROUP2:
00325                         if (alpha_insn->regB != REG_LIT)
00326                                 sprintf(insnstr, "%-10s %s%s,%s %s%s,%s %s", A_NAME, A_REG_A, cs_symbol, cs_default, A_REG_B, cs_symbol, cs_default, A_REG_C);
00327                         else
00328                                 sprintf(insnstr, "%-10s %s%s,%s %s0x%lx%s,%s %s", A_NAME, A_REG_A, cs_symbol, cs_default, cs_number, alpha_insn->data, cs_symbol, cs_default, A_REG_C);
00329                         break;
00330                 case ALPHA_GROUP3:
00331                 case ALPHA_GROUP_FLD:
00332                 case ALPHA_GROUP4:
00333                 case ALPHA_GROUP_FST: {
00334                         short sdata = (short)(alpha_insn->data&0xffff);
00335                         char c;
00336                         if (sdata<0) {
00337                                 c = '-';
00338                                 sdata = -sdata;
00339                         } else {
00340                                 c = '+';
00341                         }
00342                         sprintf(insnstr, "%-10s %s%s, [%s%s%s%c%s0x%x%s]", A_NAME, A_REG_A, cs_symbol, cs_default, A_REG_B, cs_symbol, c, cs_number, sdata, cs_symbol);
00343                         break;
00344                 }
00345                 case ALPHA_GROUP_I2F:
00346                 case ALPHA_GROUP_F2I:
00347                         sprintf(insnstr, "%-10s %s%s,%s %s", A_NAME, A_REG_A, cs_symbol, cs_default, A_REG_C);
00348                         break;
00349                 case ALPHA_GROUP_BRA:
00350                 case ALPHA_GROUP_FBR: {
00351                         CPU_ADDR caddr;
00352                         caddr.addr32.offset = (dword)alpha_insn->data;
00353                         int slen;
00354                         char *p;
00355                         char *s = (addr_sym_func) ? addr_sym_func(caddr, &slen, addr_sym_func_context) : 0;
00356                         if (s) {
00357                                 p = insnstr+sprintf(insnstr, "%-10s %s%s,%s ", A_NAME, A_REG_A, cs_symbol, cs_default);
00358                                 memmove(p, s, slen);
00359                                 p[slen] = 0;
00360                         } else {
00361                                 sprintf(insnstr, "%-10s %s%s, %s0x%x", A_NAME, A_REG_A, cs_symbol, cs_number, (dword)alpha_insn->data);
00362                         }
00363                         break;
00364                 }
00365                 case ALPHA_GROUP_JMP: {
00366                         CPU_ADDR caddr;
00367                         caddr.addr32.offset = (dword)alpha_insn->data;
00368                         int slen;
00369                         char *s = (addr_sym_func) ? addr_sym_func(caddr, &slen, addr_sym_func_context) : 0;
00370                         if (s) {
00371                                 char *p = insnstr + sprintf(insnstr, "%-10s %s %s(%s%s%s),%s ", A_NAME, A_REG_A, cs_symbol, cs_default, A_REG_B, cs_symbol, cs_default);
00372                                 memmove(p, s, slen);
00373                                 p[slen] = 0;
00374                         } else {
00375                                 sprintf(insnstr, "%-10s %s %s(%s%s%s), %s0x%x", A_NAME, A_REG_A, cs_symbol, cs_default, A_REG_B, cs_symbol, cs_number, (dword)alpha_insn->data);
00376                         }
00377                         break;
00378                 }
00379                 case ALPHA_GROUP_PAL:
00380                         sprintf(insnstr, "%-10s %s0x%08lx", A_NAME, cs_number, alpha_insn->data);
00381                         break;
00382                 default:
00383                         goto is_invalid;
00384         }
00385         disable_highlighting();
00386         return insnstr;     
00387 }
00388 
00389 bool    Alphadis::validInsn(dis_insn *disasm_insn)
00390 {
00391         return ((alphadis_insn *)disasm_insn)->valid;
00392 }
00393 

Generated on Fri May 7 21:15:28 2004 by doxygen 1.3.5