"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

alpha.c

Go to the documentation of this file.
00001 /*
00002  * alpha.c - Alpha ISA definition routines
00003  *
00004  * This file is a part of the SimpleScalar tool suite written by
00005  * Todd M. Austin as a part of the Multiscalar Research Project.
00006  *  
00007  * The tool suite is currently maintained by Doug Burger and Todd M. Austin.
00008  * 
00009  * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin
00010  *
00011  * This source file is distributed "as is" in the hope that it will be
00012  * useful.  The tool set comes with no warranty, and no author or
00013  * distributor accepts any responsibility for the consequences of its
00014  * use. 
00015  * 
00016  * Everyone is granted permission to copy, modify and redistribute
00017  * this tool set under the following conditions:
00018  * 
00019  *    This source code is distributed for non-commercial use only. 
00020  *    Please contact the maintainer for restrictions applying to 
00021  *    commercial use.
00022  *
00023  *    Permission is granted to anyone to make or distribute copies
00024  *    of this source code, either as received or modified, in any
00025  *    medium, provided that all copyright notices, permission and
00026  *    nonwarranty notices are preserved, and that the distributor
00027  *    grants the recipient permission for further redistribution as
00028  *    permitted by this document.
00029  *
00030  *    Permission is granted to distribute this file in compiled
00031  *    or executable form under the same conditions that apply for
00032  *    source code, provided that either:
00033  *
00034  *    A. it is accompanied by the corresponding machine-readable
00035  *       source code,
00036  *    B. it is accompanied by a written offer, with no time limit,
00037  *       to give anyone a machine-readable copy of the corresponding
00038  *       source code in return for reimbursement of the cost of
00039  *       distribution.  This written offer must permit verbatim
00040  *       duplication by anyone, or
00041  *    C. it is distributed by someone who received only the
00042  *       executable form, and is accompanied by a copy of the
00043  *       written offer of source code that they received concurrently.
00044  *
00045  * In other words, you are welcome to use, share and improve this
00046  * source file.  You are forbidden to forbid anyone else to use, share
00047  * and improve what you give them.
00048  *
00049  * INTERNET: dburger@cs.wisc.edu
00050  * US Mail:  1210 W. Dayton Street, Madison, WI 53706
00051  *
00052  * $Id: alpha.c,v 1.1.1.1 2000/05/26 15:22:27 taustin Exp $
00053  *
00054  * $Log: alpha.c,v $
00055  * Revision 1.1.1.1  2000/05/26 15:22:27  taustin
00056  * SimpleScalar Tool Set
00057  *
00058  *
00059  * Revision 1.4  1999/12/31 18:55:19  taustin
00060  * quad_t naming conflicts removed
00061  * decoders are more bulletproof (check for array overflows)
00062  *
00063  * Revision 1.3  1999/12/13 18:58:56  taustin
00064  * cross endian execution support added
00065  *
00066  * Revision 1.2  1998/08/31 17:15:58  taustin
00067  * added register checksuming support
00068  *
00069  * Revision 1.1  1998/08/27 16:53:27  taustin
00070  * Initial revision
00071  *
00072  * Revision 1.1  1998/05/06  01:08:39  calder
00073  * Initial revision
00074  *
00075  * Revision 1.4  1997/03/11  01:40:38  taustin
00076  * updated copyrights
00077  * long/int tweaks made for ALPHA target support
00078  * supported added for non-GNU C compilers
00079  * ss_print_insn() can now tolerate bogus insts (for DLite!)
00080  *
00081  * Revision 1.3  1997/01/06  16:07:24  taustin
00082  * comments updated
00083  * functional unit definitions moved from ss.def
00084  *
00085  * Revision 1.1  1996/12/05  18:52:32  taustin
00086  * Initial revision
00087  *
00088  *
00089  */
00090 
00091 #include <stdio.h>
00092 #include <stdlib.h>
00093 
00094 #include "host.h"
00095 #include "misc.h"
00096 #include "machine.h"
00097 #include "eval.h"
00098 #include "regs.h"
00099 
00100 #if 0 /* cross-endian execution now works with EIO trace files only... */
00101 /* FIXME: currently SimpleScalar/AXP only builds on little-endian... */
00102 #if !defined(BYTES_LITTLE_ENDIAN) || !defined(WORDS_LITTLE_ENDIAN)
00103 #error SimpleScalar/AXP only builds on little-endian machines...
00104 #endif
00105 #endif
00106 
00107 /* FIXME: currently SimpleScalar/AXP only builds with qword support... */
00108 #if !defined(HOST_HAS_QWORD)
00109 #error SimpleScalar/AXP only builds on hosts with builtin qword support...
00110 #error Try building with GNU GCC, as it supports qwords on most machines.
00111 #endif
00112 
00113 /* preferred nop instruction definition */
00114 md_inst_t MD_NOP_INST = 0x43ff041f;             /* addq r31,r31,r31 */
00115 
00116 /* opcode mask -> enum md_opcodem, used by decoder (MD_OP_ENUM()) */
00117 enum md_opcode md_mask2op[MD_MAX_MASK+1];
00118 unsigned int md_opoffset[OP_MAX];
00119 
00120 /* enum md_opcode -> mask for decoding next level */
00121 unsigned int md_opmask[OP_MAX] = {
00122   0, /* NA */
00123 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) 0,
00124 #define DEFLINK(OP,MSK,NAME,SHIFT,MASK) MASK,
00125 #define CONNECT(OP)
00126 #include "machine.def"
00127 };
00128 
00129 /* enum md_opcode -> shift for decoding next level */
00130 unsigned int md_opshift[OP_MAX] = {
00131   0, /* NA */
00132 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) 0,
00133 #define DEFLINK(OP,MSK,NAME,SHIFT,MASK) SHIFT,
00134 #define CONNECT(OP)
00135 #include "machine.def"
00136 };
00137 
00138 /* enum md_opcode -> description string */
00139 char *md_op2name[OP_MAX] = {
00140   NULL, /* NA */
00141 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) NAME,
00142 #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) NAME,
00143 #define CONNECT(OP)
00144 #include "machine.def"
00145 };
00146 
00147 /* enum md_opcode -> opcode operand format, used by disassembler */
00148 char *md_op2format[OP_MAX] = {
00149   NULL, /* NA */
00150 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) OPFORM,
00151 #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) NULL,
00152 #define CONNECT(OP)
00153 #include "machine.def"
00154 };
00155 
00156 /* enum md_opcode -> enum md_fu_class, used by performance simulators */
00157 enum md_fu_class md_op2fu[OP_MAX] = {
00158   FUClamd_NA, /* NA */
00159 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) RES,
00160 #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) FUClamd_NA,
00161 #define CONNECT(OP)
00162 #include "machine.def"
00163 };
00164 
00165 /* enum md_fu_class -> description string */
00166 char *md_fu2name[NUM_FU_CLASSES] = {
00167   NULL, /* NA */
00168   "fu-int-ALU",
00169   "fu-int-multiply",
00170   "fu-int-divide",
00171   "fu-FP-add/sub",
00172   "fu-FP-comparison",
00173   "fu-FP-conversion",
00174   "fu-FP-multiply",
00175   "fu-FP-divide",
00176   "fu-FP-sqrt",
00177   "rd-port",
00178   "wr-port"
00179 };
00180 
00181 char *md_amode_str[md_amode_NUM] =
00182 {
00183   "(const)",            /* immediate addressing mode */
00184   "(gp + const)",       /* global data access through global pointer */
00185   "(sp + const)",       /* stack access through stack pointer */
00186   "(fp + const)",       /* stack access through frame pointer */
00187   "(reg + const)",      /* (reg + const) addressing */
00188   "(reg + reg)"         /* (reg + reg) addressing */
00189 };
00190 
00191 /* symbolic register names, parser is case-insensitive */
00192 struct md_reg_names_t md_reg_names[] =
00193 {
00194   /* name */    /* file */      /* reg */
00195 
00196   /* integer register file */
00197   { "$r0",      rt_gpr,         0 },
00198   { "$v0",      rt_gpr,         0 },
00199   { "$r1",      rt_gpr,         1 },
00200   { "$r2",      rt_gpr,         2 },
00201   { "$r3",      rt_gpr,         3 },
00202   { "$r4",      rt_gpr,         4 },
00203   { "$r5",      rt_gpr,         5 },
00204   { "$r6",      rt_gpr,         6 },
00205   { "$r7",      rt_gpr,         7 },
00206   { "$err",     rt_gpr,         7 },
00207   { "$r8",      rt_gpr,         8 },
00208   { "$r9",      rt_gpr,         9 },
00209   { "$r10",     rt_gpr,         10 },
00210   { "$r11",     rt_gpr,         11 },
00211   { "$r12",     rt_gpr,         12 },
00212   { "$r13",     rt_gpr,         13 },
00213   { "$r14",     rt_gpr,         14 },
00214   { "$r15",     rt_gpr,         15 },
00215   { "$fp",      rt_gpr,         15 },
00216   { "$r16",     rt_gpr,         16 },
00217   { "$a0",      rt_gpr,         16 },
00218   { "$r17",     rt_gpr,         17 },
00219   { "$a1",      rt_gpr,         17 },
00220   { "$r18",     rt_gpr,         18 },
00221   { "$a2",      rt_gpr,         18 },
00222   { "$r19",     rt_gpr,         19 },
00223   { "$a3",      rt_gpr,         19 },
00224   { "$r20",     rt_gpr,         20 },
00225   { "$a4",      rt_gpr,         20 },
00226   { "$r21",     rt_gpr,         21 },
00227   { "$a5",      rt_gpr,         21 },
00228   { "$r22",     rt_gpr,         22 },
00229   { "$r23",     rt_gpr,         23 },
00230   { "$r24",     rt_gpr,         24 },
00231   { "$r25",     rt_gpr,         25 },
00232   { "$r26",     rt_gpr,         26 },
00233   { "$ra",      rt_gpr,         26 },
00234   { "$r27",     rt_gpr,         27 },
00235   { "$r28",     rt_gpr,         28 },
00236   { "$r29",     rt_gpr,         29 },
00237   { "$gp",      rt_gpr,         29 },
00238   { "$r30",     rt_gpr,         30 },
00239   { "$sp",      rt_gpr,         30 },
00240   { "$r31",     rt_gpr,         31 },
00241   { "$zero",    rt_gpr,         31 },
00242 
00243   /* floating point register file - double precision */
00244   { "$f0",      rt_fpr,         0 },
00245   { "$f1",      rt_fpr,         1 },
00246   { "$f2",      rt_fpr,         2 },
00247   { "$f3",      rt_fpr,         3 },
00248   { "$f4",      rt_fpr,         4 },
00249   { "$f5",      rt_fpr,         5 },
00250   { "$f6",      rt_fpr,         6 },
00251   { "$f7",      rt_fpr,         7 },
00252   { "$f8",      rt_fpr,         8 },
00253   { "$f9",      rt_fpr,         9 },
00254   { "$f10",     rt_fpr,         10 },
00255   { "$f11",     rt_fpr,         11 },
00256   { "$f12",     rt_fpr,         12 },
00257   { "$f13",     rt_fpr,         13 },
00258   { "$f14",     rt_fpr,         14 },
00259   { "$f15",     rt_fpr,         15 },
00260   { "$f16",     rt_fpr,         16 },
00261   { "$f17",     rt_fpr,         17 },
00262   { "$f18",     rt_fpr,         18 },
00263   { "$f19",     rt_fpr,         19 },
00264   { "$f20",     rt_fpr,         20 },
00265   { "$f21",     rt_fpr,         21 },
00266   { "$f22",     rt_fpr,         22 },
00267   { "$f23",     rt_fpr,         23 },
00268   { "$f24",     rt_fpr,         24 },
00269   { "$f25",     rt_fpr,         25 },
00270   { "$f26",     rt_fpr,         26 },
00271   { "$f27",     rt_fpr,         27 },
00272   { "$f28",     rt_fpr,         28 },
00273   { "$f29",     rt_fpr,         29 },
00274   { "$f30",     rt_fpr,         30 },
00275   { "$f31",     rt_fpr,         31 },
00276 
00277   /* floating point register file - integer precision */
00278   { "$l0",      rt_lpr,         0 },
00279   { "$l1",      rt_lpr,         1 },
00280   { "$l2",      rt_lpr,         2 },
00281   { "$l3",      rt_lpr,         3 },
00282   { "$l4",      rt_lpr,         4 },
00283   { "$l5",      rt_lpr,         5 },
00284   { "$l6",      rt_lpr,         6 },
00285   { "$l7",      rt_lpr,         7 },
00286   { "$l8",      rt_lpr,         8 },
00287   { "$l9",      rt_lpr,         9 },
00288   { "$l10",     rt_lpr,         10 },
00289   { "$l11",     rt_lpr,         11 },
00290   { "$l12",     rt_lpr,         12 },
00291   { "$l13",     rt_lpr,         13 },
00292   { "$l14",     rt_lpr,         14 },
00293   { "$l15",     rt_lpr,         15 },
00294   { "$l16",     rt_lpr,         16 },
00295   { "$l17",     rt_lpr,         17 },
00296   { "$l18",     rt_lpr,         18 },
00297   { "$l19",     rt_lpr,         19 },
00298   { "$l20",     rt_lpr,         20 },
00299   { "$l21",     rt_lpr,         21 },
00300   { "$l22",     rt_lpr,         22 },
00301   { "$l23",     rt_lpr,         23 },
00302   { "$l24",     rt_lpr,         24 },
00303   { "$l25",     rt_lpr,         25 },
00304   { "$l26",     rt_lpr,         26 },
00305   { "$l27",     rt_lpr,         27 },
00306   { "$l28",     rt_lpr,         28 },
00307   { "$l29",     rt_lpr,         29 },
00308   { "$l30",     rt_lpr,         30 },
00309   { "$l31",     rt_lpr,         31 },
00310 
00311   /* miscellaneous registers */
00312   { "$fpcr",    rt_ctrl,        0 },
00313   { "$uniq",    rt_ctrl,        1 },
00314 
00315   /* program counters */
00316   { "$pc",      rt_PC,          0 },
00317   { "$npc",     rt_NPC,         0 },
00318 
00319   /* sentinel */
00320   { NULL,       rt_gpr,         0 }
00321 };
00322 
00323 /* returns a register name string */
00324 char *
00325 md_reg_name(enum md_reg_type rt, int reg)
00326 {
00327   int i;
00328 
00329   for (i=0; md_reg_names[i].str != NULL; i++)
00330     {
00331       if (md_reg_names[i].file == rt && md_reg_names[i].reg == reg)
00332         return md_reg_names[i].str;
00333     }
00334 
00335   /* no found... */
00336   return NULL;
00337 }
00338 
00339 char *                                          /* err str, NULL for no err */
00340 md_reg_obj(struct regs_t *regs,                 /* registers to access */
00341            int is_write,                        /* access type */
00342            enum md_reg_type rt,                 /* reg bank to probe */
00343            int reg,                             /* register number */
00344            struct eval_value_t *val)            /* input, output */
00345 {
00346   switch (rt)
00347     {
00348     case rt_gpr:
00349       if (reg < 0 || reg >= MD_NUM_IREGS)
00350         return "register number out of range";
00351 
00352       if (!is_write)
00353         {
00354           val->type = et_qword;
00355           val->value.as_qword = regs->regs_R[reg];
00356         }
00357       else
00358         regs->regs_R[reg] = eval_as_qword(*val);
00359       break;
00360 
00361     case rt_lpr:
00362       if (reg < 0 || reg >= MD_NUM_FREGS)
00363         return "register number out of range";
00364 
00365       if (!is_write)
00366         {
00367           val->type = et_qword;
00368           val->value.as_qword = regs->regs_F.q[reg];
00369         }
00370       else
00371         regs->regs_F.q[reg] = eval_as_qword(*val);
00372       break;
00373 
00374     case rt_fpr:
00375       if (reg < 0 || reg >= MD_NUM_FREGS)
00376         return "register number out of range";
00377 
00378       if (!is_write)
00379         {
00380           val->type = et_double;
00381           val->value.as_double = regs->regs_F.d[reg];
00382         }
00383       else
00384         regs->regs_F.d[reg] = eval_as_double(*val);
00385       break;
00386 
00387     case rt_ctrl:
00388       switch (reg)
00389         {
00390         case /* FPCR */0:
00391           if (!is_write)
00392             {
00393               val->type = et_qword;
00394               val->value.as_qword = regs->regs_C.fpcr;
00395             }
00396           else
00397             regs->regs_C.fpcr = eval_as_qword(*val);
00398           break;
00399 
00400         case /* UNIQ */1:
00401           if (!is_write)
00402             {
00403               val->type = et_qword;
00404               val->value.as_qword = regs->regs_C.uniq;
00405             }
00406           else
00407             regs->regs_C.uniq = eval_as_qword(*val);
00408           break;
00409 
00410         default:
00411           return "register number out of range";
00412         }
00413       break;
00414 
00415     case rt_PC:
00416       if (!is_write)
00417         {
00418           val->type = et_addr;
00419           val->value.as_addr = regs->regs_PC;
00420         }
00421       else
00422         regs->regs_PC = eval_as_addr(*val);
00423       break;
00424 
00425     case rt_NPC:
00426       if (!is_write)
00427         {
00428           val->type = et_addr;
00429           val->value.as_addr = regs->regs_NPC;
00430         }
00431       else
00432         regs->regs_NPC = eval_as_addr(*val);
00433       break;
00434 
00435     default:
00436       panic("bogus register bank");
00437     }
00438 
00439   /* no error */
00440   return NULL;
00441 }
00442 
00443 /* print integer REG(S) to STREAM */
00444 void
00445 md_print_ireg(md_gpr_t regs, int reg, FILE *stream)
00446 {
00447   myfprintf(stream, "%4s: %16ld/0x%012lx",
00448             md_reg_name(rt_gpr, reg), regs[reg], regs[reg]);
00449 }
00450 
00451 void
00452 md_print_iregs(md_gpr_t regs, FILE *stream)
00453 {
00454   int i;
00455 
00456   for (i=0; i < MD_NUM_IREGS; i += 2)
00457     {
00458       md_print_ireg(regs, i, stream);
00459       fprintf(stream, "  ");
00460       md_print_ireg(regs, i+1, stream);
00461       fprintf(stream, "\n");
00462     }
00463 }
00464 
00465 /* print floating point REGS to STREAM */
00466 void
00467 md_print_fpreg(md_fpr_t regs, int reg, FILE *stream)
00468 {
00469   myfprintf(stream, "%4s: %16ld/0x%012lx/%f",
00470             md_reg_name(rt_fpr, reg), regs.q[reg], regs.q[reg], regs.d[reg]);
00471 }
00472 
00473 void
00474 md_print_fpregs(md_fpr_t regs, FILE *stream)
00475 {
00476   int i;
00477 
00478   /* floating point registers */
00479   for (i=0; i < MD_NUM_FREGS; i += 2)
00480     {
00481       md_print_fpreg(regs, i, stream);
00482       fprintf(stream, "\n");
00483 
00484       md_print_fpreg(regs, i+1, stream);
00485       fprintf(stream, "\n");
00486     }
00487 }
00488 
00489 void
00490 md_print_creg(md_ctrl_t regs, int reg, FILE *stream)
00491 {
00492   /* index is only used to iterate over these registers, hence no enums... */
00493   switch (reg)
00494     {
00495     case 0:
00496       myfprintf(stream, "FPCR: 0x%012lx", regs.fpcr);
00497       break;
00498 
00499     case 1:
00500       myfprintf(stream, "UNIQ: 0x%012lx", regs.uniq);
00501       break;
00502 
00503     default:
00504       panic("bogus control register index");
00505     }
00506 }
00507 
00508 void
00509 md_print_cregs(md_ctrl_t regs, FILE *stream)
00510 {
00511   md_print_creg(regs, 0, stream);
00512   fprintf(stream, "  ");
00513   md_print_creg(regs, 1, stream);
00514   fprintf(stream, "\n");
00515 }
00516 
00517 /* xor checksum registers */
00518 word_t
00519 md_xor_regs(struct regs_t *regs)
00520 {
00521   int i;
00522   qword_t checksum = 0;
00523 
00524   for (i=0; i < (MD_NUM_IREGS-1); i++)
00525     checksum ^= regs->regs_R[i];
00526 
00527   for (i=0; i < (MD_NUM_FREGS-1); i++)
00528     checksum ^= regs->regs_F.q[i];
00529 
00530   checksum ^= regs->regs_C.fpcr;
00531   checksum ^= regs->regs_C.uniq;
00532   checksum ^= regs->regs_PC;
00533   checksum ^= regs->regs_NPC;
00534 
00535   return (word_t)((checksum >> 32) ^ checksum);
00536 }
00537 
00538 
00539 /* enum md_opcode -> opcode flags, used by simulators */
00540 unsigned int md_op2flags[OP_MAX] = {
00541   NA, /* NA */
00542 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) FLAGS,
00543 #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) NA,
00544 #define CONNECT(OP)
00545 #include "machine.def"
00546 };
00547 
00548 
00549 /* intialize the inst decoder, this function builds the ISA decode tables */
00550 void
00551 md_init_decoder(void)
00552 {
00553   unsigned long max_offset = 0;
00554   unsigned long offset = 0;
00555 
00556 #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)            \
00557   if ((MSK)+offset >= MD_MAX_MASK)                                      \
00558     panic("MASK_MAX is too small, index==%d", (MSK)+offset);            \
00559   if (md_mask2op[(MSK)+offset])                                         \
00560     fatal("doubly defined opcode, index==%d", (MSK)+offset);            \
00561   md_mask2op[(MSK)+offset]=(OP); max_offset=MAX(max_offset,(MSK)+offset);
00562 
00563 #define DEFLINK(OP,MSK,NAME,MASK,SHIFT)                                 \
00564   if ((MSK)+offset >= MD_MAX_MASK)                                      \
00565     panic("MASK_MAX is too small, index==%d", (MSK)+offset);            \
00566   if (md_mask2op[(MSK)+offset])                                         \
00567     fatal("doubly defined opcode, index==%d", (MSK)+offset);            \
00568   md_mask2op[(MSK)+offset]=(OP); max_offset=MAX(max_offset,(MSK)+offset);
00569 
00570 #define CONNECT(OP)                                                     \
00571     offset = max_offset+1; md_opoffset[OP] = offset;
00572 
00573 #include "machine.def"
00574 
00575   if (max_offset >= MD_MAX_MASK)
00576     panic("MASK_MAX is too small, index==%d", max_offset);
00577 }
00578 
00579 /* disassemble an Alpha instruction */
00580 void
00581 md_print_insn(md_inst_t inst,           /* instruction to disassemble */
00582               md_addr_t pc,             /* addr of inst, used for PC-rels */
00583               FILE *stream)             /* output stream */
00584 {
00585   enum md_opcode op;
00586 
00587   /* use stderr as default output stream */
00588   if (!stream)
00589     stream = stderr;
00590 
00591   /* decode the instruction, assumes predecoded text segment */
00592   MD_SET_OPCODE(op, inst);
00593 
00594   /* disassemble the instruction */
00595   if (op <= OP_NA || op >= OP_MAX)
00596     {
00597       /* bogus instruction */
00598       fprintf(stream, "<invalid inst: 0x%08x>", inst);
00599     }
00600   else
00601     {
00602       char *s;
00603 
00604       /* FIXME: %-10s crashes on Suns!!! */
00605       fprintf(stream, "%s ", MD_OP_NAME(op));
00606 
00607       s = MD_OP_FORMAT(op);
00608       while (*s) {
00609         switch (*s) {
00610         case 'a':
00611           fprintf(stream, "r%d", RA);
00612           break;
00613         case 'b':
00614           fprintf(stream, "r%d", RB);
00615           break;
00616         case 'c':
00617           fprintf(stream, "r%d", RC);
00618           break;
00619         case 'A':
00620           fprintf(stream, "f%d", RA);
00621           break;
00622         case 'B':
00623           fprintf(stream, "f%d", RB);
00624           break;
00625         case 'C':
00626           fprintf(stream, "f%d", RC);
00627           break;
00628         case 'o':
00629           fprintf(stream, "%d", (sword_t)SEXT(OFS));
00630           break;
00631         case 'j':
00632           myfprintf(stream, "0x%p", pc + (SEXT(OFS) << 2) + 4);
00633           break;
00634         case 'J':
00635           myfprintf(stream, "0x%p", pc + (SEXT21(TARG) << 2) + 4);
00636           break;
00637         case 'i':
00638           fprintf(stream, "%d", (word_t)IMM);
00639           break;
00640         default:
00641           /* anything unrecognized, e.g., '.' is just passed through */
00642           fputc(*s, stream);
00643         }
00644         s++;
00645       }
00646     }
00647 }


UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214