hppa/decoder_low.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000-2001, The University of Queensland
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:        decoder_low.m
00012  * OVERVIEW:    Low level New Jersey Machine Code Toolkit match file for the
00013  *              HP Pa/risc architecture (basically PA/RISC version 1.1)
00014  *============================================================================*/
00015 
00016 /*
00017  * $Revision: 1.1 $
00018  *
00019  * 30 Nov 00 - Simon: Created
00020  * 22 Mar 01 - Simon: fixed low_sign_ext problem with ADDI
00021  * 04 May 01 - Mike: c_cc -> c_c for consistency; fixed a problem with c_null
00022  *              that seems to be a result of the merge
00023  * 04 May 01 - Mike: Generate RTLs now instead of strings
00024  * 19 Jul 01 - Simon: Updated integer/float loads/stores and LDO
00025  * 23 Jul 01 - Mike: Added "not_used" to quelch annoying warnings
00026  * 25 Jul 01 - Simon: Added shift, extract, deposit
00027  * 07 Aug 01 - Simon: Changed iloads and istores to take more parameters, so
00028  *              that the addressing mode details are explicit in the SSL now
00029  * 10 Aug 01 - Simon: Moved decoder_low.m:c_bit() to decoder.m:dis_c_bit()
00030  * 13 Aug 01 - Mike: Provide address with "Undecoded instruction" message
00031  * 22 Aug 01 - Mike: Fixed a warning with "notused(nulli)"
00032  */
00033 
00034 
00035 #include "global.h"
00036 #include "decoder.h"
00037 #include "hppa-names.h"
00038 #include "rtl.h"
00039 
00040 void c_null(ADDRESS hostpc, char **garble);
00041 unsigned long c_wcr(ADDRESS hostpc, char **garble);
00042 bool c_c_n(ADDRESS hostpc);
00043 void addr(ADDRESS hostpc);
00044 
00045 // The below is used to quelch annoying "variable not used" warnings
00046 void not_used(int unwanted)
00047 {
00048     unwanted = 0;
00049 }
00050 
00051 DWord getDword (unsigned lc)
00052 /* get4Bytes - returns next 4-Byte from image pointed to by lc.
00053    Fetch in a big-endian manner  */
00054 {
00055     return
00056       (DWord)
00057       ((((((
00058           *(Byte *)lc << 8
00059       ) + *(Byte *)(lc+1)) << 8
00060       ) + *(Byte *)(lc+2)) << 8
00061       ) + *(Byte *)(lc+3));
00062 }
00063 
00064 bool c_c_n(ADDRESS hostpc)
00065 {
00066     bool result = true;
00067     match hostpc to
00068       | c_c_nonneg() => { result = true; }
00069       | c_c_neg() =>    { result = false; }
00070     endmatch
00071     return result;
00072 }
00073 
00074 SemStr* NJMCDecoder::c_c(ADDRESS hostpc, int &cond)
00075 {
00076   static const char *c_c_names = {
00077                 "c_c_no", "c_c_eq", "c_c_l", "c_c_le", "c_c_ul", "c_c_ule", "c_c_sv",
00078                 "c_c_od", "c_c_yes", "c_c_ne", "c_c_ge", "c_c_g", "c_c_uge", "c_c_ug",
00079                 "c_c_nsv", "c_c_ev"
00080         };
00081   static const int cmpib_codes = { 4, 1, 2, 3, 12, 9, 10, 11 };
00082   static const int sep_codes = { 0, 1, 2, 7, 8, 9, 10, 15 };
00083   match hostpc to
00084         | c_arith_w(c3,cmplt) => {
00085             cond = c3 + (c_c_n(cmplt)?0:8); 
00086         }
00087         | c_arith_dw(c3,cmplt) => {
00088             cond = c3 + (c_c_n(cmplt)?0:8); 
00089         }
00090         | c_arith_none() => {
00091             cond = 0;
00092         }
00093         | c_sep(c3_16) => {
00094             cond = sep_codes;
00095         }
00096         | c_cmpb_w(c3,cmplt) => {
00097             cond = c3 + (c_c_n(cmplt)?0:8); 
00098         }
00099         | c_cmpb_dw(c3,cmplt) => {
00100             cond = c3 + (c_c_n(cmplt)?0:8); 
00101         }
00102         | c_cmpib_dw(c3) => {
00103             cond = cmpib_codes;
00104         }
00105         | c_bbs_w(c) => {
00106             cond = 1 + (c?0:8); 
00107         }
00108         | c_bbs_dw(c) => {
00109             cond = 1 + (c?0:8); 
00110         }
00111         else {
00112             cond = 0;
00113         }
00114   endmatch
00115   return instantiateNamedParam(c_c_names[cond]);
00116 }
00117 
00118 unsigned long c_wcr(ADDRESS hostpc, char **garble)
00119 {
00120 #if 0
00121   unsigned long regl;
00122   match hostpc to
00123     | c_mfctl(r_06) => {
00124         regl = r_06;
00125     }
00126     | c_mfctl_w() => {
00127         *garble += sprintf(*garble,".w");
00128         regl = 11;
00129     }
00130     else {
00131         regl = 0;
00132         //sprintf("#c_WCR%08X#", getDword(hostpc));
00133     }
00134   endmatch
00135   return regl;
00136 #else
00137     return 0;
00138 #endif
00139 }
00140 
00141 void c_null(ADDRESS hostpc, char **garble)
00142 {
00143 #if 0
00144   match hostpc to
00145     | c_br_nnull() => {
00146     }
00147     | c_br_null() => {
00148         *garble += sprintf(*garble, ".n");
00149     }
00150     else {
00151         //printf("#c_NULL%08X#", getDword(hostpc));
00152     }
00153   endmatch
00154 #endif
00155 }
00156 
00157 /*==============================================================================
00158  * FUNCTION:       NJMCDecoder::decodeLowLevelInstruction
00159  * OVERVIEW:       Decodes a machine instruction and returns an instantiated
00160  *                  list of RTs.
00161  * NOTE:           A side effect of decoding the completers is that there may
00162  *                  be some semantics added to members preInstSem or postInstSem
00163  *                  This is made part of the final RTL in decoder.m
00164  * PARAMETERS:     hostPC - the address of the pc in the loaded Elf object
00165  *                 pc - the virtual address of the pc
00166  *                 result - a reference parameter that has a fields for the
00167  *                  number of bytes decoded, their validity, etc
00168  * RETURNS:        the instantiated list of RTs
00169  *============================================================================*/
00170 list<RT*>* NJMCDecoder::decodeLowLevelInstruction (ADDRESS hostPC, ADDRESS pc,
00171                         DecodeResult& result)
00172 {
00173     ADDRESS nextPC; 
00174   
00175     list<RT*>* RTs = NULL;
00176     int condvalue;
00177     match  hostPC to
00178         | arith(cmplt,r_11,r_06,t_27) => {
00179             /*  Arith,cc_16   r_11, r_06, t_27 */
00180             RTs = instantiate(pc, name, dis_Reg(r_11), dis_Reg(r_06),
00181               dis_Reg(t_27),c_c(cmplt, condvalue));
00182         }
00183         | arith_imm(cmplt, imm11, r_06, t_11) => {
00184             /* arith_imm,cc_16 imm11!,r_06,t_11 */
00185             RTs = instantiate(pc, name, dis_Num(imm11), dis_Reg(r_06),
00186               dis_Reg(t_11), c_c(cmplt, condvalue));
00187         }
00188         | ADDIL(imm21, r_06) => {
00189             RTs = instantiate(pc, name, dis_Num(imm21), dis_Reg(r_06));
00190         }
00191         | LDIL(imm21, t_06) => {
00192             RTs = instantiate(pc, name, dis_Num(imm21), dis_Reg(t_06));
00193         }
00194         | iloads(c_addr, xd, s, b,t_27) => {
00195             RTs = instantiate(pc, name, dis_c_addr(c_addr),
00196                 dis_xd(xd), dis_Sreg(s),
00197                 dis_Reg(b), dis_Reg(t_27));
00198         }
00199         | istores(c_addr,r_11, xd, s, b) => {
00200             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_Reg(r_11),
00201                 dis_xd(xd), dis_Sreg(s), dis_Reg(b));
00202         }
00203         | fwloads(c_addr, xd, s, b, t_27) => {
00204             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_xd(xd),
00205                 dis_Sreg(s), dis_Reg(b), dis_Freg(t_27, 0));
00206         }
00207         | fwstores(c_addr, r_27, xd, s, b) => {
00208             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_Freg(r_27, 0),
00209                 dis_xd(xd), dis_Sreg(s), dis_Reg(b));
00210         }
00211         | fdloads(c_addr, xd, s, b, t_27) => {
00212             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_xd(xd),
00213                 dis_Sreg(s), dis_Reg(b), dis_Freg(t_27, 1));
00214         }
00215         | fdstores(c_addr, r_27, xd, s, b) => {
00216             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_Freg(r_27, 1),
00217                 dis_xd(xd), dis_Sreg(s), dis_Reg(b));
00218         }
00219         | iloads_ldisp(c_addr, xd, s, b, r_11) => {
00220             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_xd(xd),
00221                 dis_Sreg(s), dis_Reg(b), dis_Reg(r_11));
00222         }
00223         | istores_ldisp(c_addr, r_11, xd, s, b) => {
00224             RTs = instantiate(pc, name, dis_c_addr(c_addr), dis_Reg(r_11),
00225                 dis_xd(xd), dis_Sreg(s), dis_Reg(b));
00226         }
00227         | LDO(ldisp, b, t) => {
00228             RTs = instantiate(pc, name, dis_Num(ldisp), dis_Reg(b), dis_Reg(t));
00229         }
00230         | VSHD(r1, r2, t, c) => {
00231             RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2), dis_Reg(t),
00232                 c_c(c, condvalue));
00233         }
00234         | SHD(r1, r2, p, t, c) => {
00235             RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2), dis_Num(p),
00236                 dis_Reg(t), c_c(c, condvalue));
00237         }
00238         | ext_var(r, len, t, c) => {
00239             RTs = instantiate(pc, name, dis_Reg(r), dis_Num(len), dis_Reg(t),
00240                 c_c(c, condvalue));
00241         }
00242         | ext_fix(r, p, len, t, c) => {
00243             RTs = instantiate(pc, name, dis_Reg(r), dis_Num(p), dis_Num(len),
00244                 dis_Reg(t), c_c(c, condvalue));
00245         }
00246         | dep_var(r, len, t, c) => {
00247             RTs = instantiate(pc, name, dis_Reg(r), dis_Num(len), dis_Reg(t),
00248                 c_c(c, condvalue));
00249         }
00250         | dep_fix(r, p, len, t, c) => {
00251             RTs = instantiate(pc, name, dis_Reg(r), dis_Num(p), dis_Num(len),
00252                 dis_Reg(t), c_c(c, condvalue));
00253         }
00254         | dep_ivar(i, len, t, c) => {
00255             RTs = instantiate(pc, name, dis_Num(i), dis_Num(len), dis_Reg(t),
00256                 c_c(c, condvalue));
00257         }
00258         | dep_ifix(i, p, len, t, c) => {
00259             RTs = instantiate(pc, name, dis_Num(i), dis_Num(p), dis_Num(len),
00260                 dis_Reg(t), c_c(c, condvalue));
00261         }
00262         | ubranch(nulli,ubr_target,t_06) => {
00263             /* ubranch,cmplt,n  target,t_06) */
00264             RTs = instantiate(pc, name, dis_Num(ubr_target), dis_Reg(t_06));
00265             not_used(nulli);
00266         }
00267         | BL.LONG(nulli,ubr_target) => {
00268             /* BL.LONG cmplt,n  target,2) */
00269             RTs = instantiate(pc, name, dis_Num(ubr_target));
00270             not_used(nulli);
00271         }
00272         | BLR(nulli,x_11,t_06) => {
00273             /* BLR,n x,t */
00274             RTs = instantiate(pc, name, dis_Reg(x_11), dis_Reg(t_06));
00275             not_used(nulli);
00276         }
00277         | BV(nulli,x_11,b_06) => {
00278             /* BV,n x_11(b_06) */
00279             RTs = instantiate(pc, name, dis_Reg(x_11), dis_Reg(b_06));
00280             not_used(nulli);
00281         }
00282         | bve(p_31,nulli,b_06) => {
00283             /* BVE.l BVE.lp BVE.p BVE  */
00284             RTs = instantiate(pc, name, p_31, dis_Reg(b_06));
00285             not_used(nulli);
00286         }
00287         | BREAK(im5_27,im13_06) => {
00288             RTs = instantiate(pc, name, dis_Num(im5_27), dis_Num(im13_06));
00289         }
00290         | sysop_i_t(im10_06,t_27) => {
00291             RTs = instantiate(pc, name, dis_Num(im10_06), dis_Reg(t_27));
00292         }
00293         | sysop_simple => {
00294             RTs = instantiate(pc, name);
00295         }
00296         | sysop_r(r_11) => {
00297             RTs = instantiate(pc, name, dis_Reg(r_11));
00298         }
00299         | sysop_cr_t(cmplt, t_27) => {
00300             RTs = instantiate(pc, name, dis_c_wcr(cmplt), dis_Reg(t_27));
00301         }
00302         | MTCTL(r_11, ct_06) => {
00303             RTs = instantiate(pc, name, dis_Reg(r_11), dis_ct(ct_06));
00304         }
00305         | MFIA(t_27) => {
00306             RTs = instantiate(pc, name, dis_Reg(t_27));
00307         }
00308 // Floating point instructions. Note that the floating point format is being
00309 // passed as an ss inf the form of an integer constant (using dis_Num())
00310         | flt_c0_all(fmt, rf, tf) => {
00311             RTs = instantiate(pc, name, dis_Num(fmt), dis_Freg(rf, fmt),
00312                 dis_Freg(tf, fmt));
00313         }
00314         | flt_c1_all(sf, df, rf, tf) => {
00315             RTs = instantiate(pc, name, dis_Num(sf), dis_Num(df),
00316                 dis_Freg(rf, sf), dis_Freg(tf, df));
00317         }
00318         | flt_c2_all(sf, df, rf, tf) => {
00319             RTs = instantiate(pc, name, dis_Num(sf), dis_Num(df),
00320                 dis_Freg(rf, sf), dis_Freg(tf, df));
00321         }
00322         | flt_c3_all(fmt, fr1, fr2, frt) => {
00323             RTs = instantiate(pc, name, dis_Num(fmt), dis_Freg(fr1, fmt),
00324                 dis_Freg(fr2, fmt), dis_Freg(frt, fmt));
00325         }
00326         | XMPYU(fr1, fr2, frt) => {
00327             // This instruction has fixed register sizes
00328             RTs = instantiate(pc, "XMPYU", dis_Freg(fr1, 0), dis_Freg(fr2, 0),
00329                 dis_Freg(frt, 1));
00330         }
00331 //      | LDSID(s2_16,b_06,t_27)[name] => {
00332 //      }
00333 //      | MTSP(r_11,sr)[name] => {
00334 //      }
00335 //      | MFSP(sr,t_27)[name] => {
00336 //      }
00337         else {
00338             //RTs = NULL;
00339             result.valid = false;
00340 cout << "Undecoded instruction " << hex << *(int*)hostPC << " at " << pc << " (opcode " << ((*(unsigned*)hostPC) >> 26) << ")\n";
00341         }
00342     endmatch
00343 
00344     result.numBytes = (nextPC - hostPC);
00345     return RTs;
00346 
00347 }
00348 
00349 /*
00350         }
00351         | LDWl(cmplt, ldisp, s2_16, b_06, t_11)[name] => {
00352                 *garble += sprintf(*garble, "%s", name);
00353             c_disps(cmplt);
00354             *garble += sprintf(*garble, "  %d(%s,%s),%s", ldisp, s2_16_names[s2_16], b_06_names[b_06], t_11_names[t_11]);
00355         
00356 */

Generated on Tue Sep 19 21:18:18 2006 for Boomerang by  doxygen 1.4.6