emit_ack.c

Go to the documentation of this file.
00001 /*      emit_ack.c - emit ACK assembly                  Author: Kees J. Bot
00002  *                   emit NCC assembly                          27 Dec 1993
00003  */
00004 #define nil 0
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <stdarg.h>
00008 #include <string.h>
00009 #include <assert.h>
00010 #include "asmconv.h"
00011 #include "token.h"
00012 #include "asm86.h"
00013 #include "languages.h"
00014 
00015 typedef struct mnemonic {       /* ACK as86 mnemonics translation table. */
00016         opcode_t        opcode;
00017         char            *name;
00018 } mnemonic_t;
00019 
00020 static mnemonic_t mnemtab[] = {
00021         { AAA,          "aaa"           },
00022         { AAD,          "aad"           },
00023         { AAM,          "aam"           },
00024         { AAS,          "aas"           },
00025         { ADC,          "adc%"          },
00026         { ADD,          "add%"          },
00027         { AND,          "and%"          },
00028         { ARPL,         "arpl"          },
00029         { BOUND,        "bound"         },
00030         { BSF,          "bsf"           },
00031         { BSR,          "bsr"           },
00032         { BSWAP,        "bswap"         },
00033         { BT,           "bt"            },
00034         { BTC,          "btc"           },
00035         { BTR,          "btr"           },
00036         { BTS,          "bts"           },
00037         { CALL,         "call"          },
00038         { CALLF,        "callf"         },
00039         { CBW,          "cbw"           },
00040         { CLC,          "clc"           },
00041         { CLD,          "cld"           },
00042         { CLI,          "cli"           },
00043         { CLTS,         "clts"          },
00044         { CMC,          "cmc"           },
00045         { CMP,          "cmp%"          },
00046         { CMPS,         "cmps%"         },
00047         { CMPXCHG,      "cmpxchg"       },
00048         { CWD,          "cwd"           },
00049         { DAA,          "daa"           },
00050         { DAS,          "das"           },
00051         { DEC,          "dec%"          },
00052         { DIV,          "div%"          },
00053         { DOT_ALIGN,    ".align"        },
00054         { DOT_ASCII,    ".ascii"        },
00055         { DOT_ASCIZ,    ".asciz"        },
00056         { DOT_ASSERT,   ".assert"       },
00057         { DOT_BASE,     ".base"         },
00058         { DOT_BSS,      ".sect .bss"    },
00059         { DOT_COMM,     ".comm"         },
00060         { DOT_DATA,     ".sect .data"   },
00061         { DOT_DATA1,    ".data1"        },
00062         { DOT_DATA2,    ".data2"        },
00063         { DOT_DATA4,    ".data4"        },
00064         { DOT_DEFINE,   ".define"       },
00065         { DOT_END,      ".sect .end"    },
00066         { DOT_EXTERN,   ".extern"       },
00067         { DOT_FILE,     ".file"         },
00068         { DOT_LCOMM,    ".comm"         },
00069         { DOT_LINE,     ".line"         },
00070         { DOT_LIST,     ".list"         },
00071         { DOT_NOLIST,   ".nolist"       },
00072         { DOT_ROM,      ".sect .rom"    },
00073         { DOT_SPACE,    ".space"        },
00074         { DOT_SYMB,     ".symb"         },
00075         { DOT_TEXT,     ".sect .text"   },
00076         { DOT_USE16,    ".use16"        },
00077         { DOT_USE32,    ".use32"        },
00078         { ENTER,        "enter"         },
00079         { F2XM1,        "f2xm1"         },
00080         { FABS,         "fabs"          },
00081         { FADD,         "fadd"          },
00082         { FADDD,        "faddd"         },
00083         { FADDP,        "faddp"         },
00084         { FADDS,        "fadds"         },
00085         { FBLD,         "fbld"          },
00086         { FBSTP,        "fbstp"         },
00087         { FCHS,         "fchs"          },
00088         { FCLEX,        "fclex"         },
00089         { FCOMD,        "fcomd"         },
00090         { FCOMPD,       "fcompd"        },
00091         { FCOMPP,       "fcompp"        },
00092         { FCOMPS,       "fcomps"        },
00093         { FCOMS,        "fcoms"         },
00094         { FCOS,         "fcos"          },
00095         { FDECSTP,      "fdecstp"       },
00096         { FDIVD,        "fdivd"         },
00097         { FDIVP,        "fdivp"         },
00098         { FDIVRD,       "fdivrd"        },
00099         { FDIVRP,       "fdivrp"        },
00100         { FDIVRS,       "fdivrs"        },
00101         { FDIVS,        "fdivs"         },
00102         { FFREE,        "ffree"         },
00103         { FIADDL,       "fiaddl"        },
00104         { FIADDS,       "fiadds"        },
00105         { FICOM,        "ficom"         },
00106         { FICOMP,       "ficomp"        },
00107         { FIDIVL,       "fidivl"        },
00108         { FIDIVRL,      "fidivrl"       },
00109         { FIDIVRS,      "fidivrs"       },
00110         { FIDIVS,       "fidivs"        },
00111         { FILDL,        "fildl"         },
00112         { FILDQ,        "fildq"         },
00113         { FILDS,        "filds"         },
00114         { FIMULL,       "fimull"        },
00115         { FIMULS,       "fimuls"        },
00116         { FINCSTP,      "fincstp"       },
00117         { FINIT,        "finit"         },
00118         { FISTL,        "fistl"         },
00119         { FISTP,        "fistp"         },
00120         { FISTS,        "fists"         },
00121         { FISUBL,       "fisubl"        },
00122         { FISUBRL,      "fisubrl"       },
00123         { FISUBRS,      "fisubrs"       },
00124         { FISUBS,       "fisubs"        },
00125         { FLD1,         "fld1"          },
00126         { FLDCW,        "fldcw"         },
00127         { FLDD,         "fldd"          },
00128         { FLDENV,       "fldenv"        },
00129         { FLDL2E,       "fldl2e"        },
00130         { FLDL2T,       "fldl2t"        },
00131         { FLDLG2,       "fldlg2"        },
00132         { FLDLN2,       "fldln2"        },
00133         { FLDPI,        "fldpi"         },
00134         { FLDS,         "flds"          },
00135         { FLDX,         "fldx"          },
00136         { FLDZ,         "fldz"          },
00137         { FMULD,        "fmuld"         },
00138         { FMULP,        "fmulp"         },
00139         { FMULS,        "fmuls"         },
00140         { FNOP,         "fnop"          },
00141         { FPATAN,       "fpatan"        },
00142         { FPREM,        "fprem"         },
00143         { FPREM1,       "fprem1"        },
00144         { FPTAN,        "fptan"         },
00145         { FRNDINT,      "frndint"       },
00146         { FRSTOR,       "frstor"        },
00147         { FSAVE,        "fsave"         },
00148         { FSCALE,       "fscale"        },
00149         { FSIN,         "fsin"          },
00150         { FSINCOS,      "fsincos"       },
00151         { FSQRT,        "fsqrt"         },
00152         { FSTCW,        "fstcw"         },
00153         { FSTD,         "fstd"          },
00154         { FSTENV,       "fstenv"        },
00155         { FSTPD,        "fstpd"         },
00156         { FSTPS,        "fstps"         },
00157         { FSTPX,        "fstpx"         },
00158         { FSTS,         "fsts"          },
00159         { FSTSW,        "fstsw"         },
00160         { FSUBD,        "fsubd"         },
00161         { FSUBP,        "fsubp"         },
00162         { FSUBPR,       "fsubpr"        },
00163         { FSUBRD,       "fsubrd"        },
00164         { FSUBRS,       "fsubrs"        },
00165         { FSUBS,        "fsubs"         },
00166         { FTST,         "ftst"          },
00167         { FUCOM,        "fucom"         },
00168         { FUCOMP,       "fucomp"        },
00169         { FUCOMPP,      "fucompp"       },
00170         { FXAM,         "fxam"          },
00171         { FXCH,         "fxch"          },
00172         { FXTRACT,      "fxtract"       },
00173         { FYL2X,        "fyl2x"         },
00174         { FYL2XP1,      "fyl2xp1"       },
00175         { HLT,          "hlt"           },
00176         { IDIV,         "idiv%"         },
00177         { IMUL,         "imul%"         },
00178         { IN,           "in%"           },
00179         { INC,          "inc%"          },
00180         { INS,          "ins%"          },
00181         { INT,          "int"           },
00182         { INTO,         "into"          },
00183         { INVD,         "invd"          },
00184         { INVLPG,       "invlpg"        },
00185         { IRET,         "iret"          },
00186         { IRETD,        "iretd"         },
00187         { JA,           "ja"            },
00188         { JAE,          "jae"           },
00189         { JB,           "jb"            },
00190         { JBE,          "jbe"           },
00191         { JCXZ,         "jcxz"          },
00192         { JE,           "je"            },
00193         { JG,           "jg"            },
00194         { JGE,          "jge"           },
00195         { JL,           "jl"            },
00196         { JLE,          "jle"           },
00197         { JMP,          "jmp"           },
00198         { JMPF,         "jmpf"          },
00199         { JNE,          "jne"           },
00200         { JNO,          "jno"           },
00201         { JNP,          "jnp"           },
00202         { JNS,          "jns"           },
00203         { JO,           "jo"            },
00204         { JP,           "jp"            },
00205         { JS,           "js"            },
00206         { LAHF,         "lahf"          },
00207         { LAR,          "lar"           },
00208         { LDS,          "lds"           },
00209         { LEA,          "lea"           },
00210         { LEAVE,        "leave"         },
00211         { LES,          "les"           },
00212         { LFS,          "lfs"           },
00213         { LGDT,         "lgdt"          },
00214         { LGS,          "lgs"           },
00215         { LIDT,         "lidt"          },
00216         { LLDT,         "lldt"          },
00217         { LMSW,         "lmsw"          },
00218         { LOCK,         "lock"          },
00219         { LODS,         "lods%"         },
00220         { LOOP,         "loop"          },
00221         { LOOPE,        "loope"         },
00222         { LOOPNE,       "loopne"        },
00223         { LSL,          "lsl"           },
00224         { LSS,          "lss"           },
00225         { LTR,          "ltr"           },
00226         { MOV,          "mov%"          },
00227         { MOVS,         "movs%"         },
00228         { MOVSX,        "movsx"         },
00229         { MOVSXB,       "movsxb"        },
00230         { MOVZX,        "movzx"         },
00231         { MOVZXB,       "movzxb"        },
00232         { MUL,          "mul%"          },
00233         { NEG,          "neg%"          },
00234         { NOP,          "nop"           },
00235         { NOT,          "not%"          },
00236         { OR,           "or%"           },
00237         { OUT,          "out%"          },
00238         { OUTS,         "outs%"         },
00239         { POP,          "pop"           },
00240         { POPA,         "popa"          },
00241         { POPF,         "popf"          },
00242         { PUSH,         "push"          },
00243         { PUSHA,        "pusha"         },
00244         { PUSHF,        "pushf"         },
00245         { RCL,          "rcl%"          },
00246         { RCR,          "rcr%"          },
00247         { RET,          "ret"           },
00248         { RETF,         "retf"          },
00249         { ROL,          "rol%"          },
00250         { ROR,          "ror%"          },
00251         { SAHF,         "sahf"          },
00252         { SAL,          "sal%"          },
00253         { SAR,          "sar%"          },
00254         { SBB,          "sbb%"          },
00255         { SCAS,         "scas%"         },
00256         { SETA,         "seta"          },
00257         { SETAE,        "setae"         },
00258         { SETB,         "setb"          },
00259         { SETBE,        "setbe"         },
00260         { SETE,         "sete"          },
00261         { SETG,         "setg"          },
00262         { SETGE,        "setge"         },
00263         { SETL,         "setl"          },
00264         { SETLE,        "setle"         },
00265         { SETNE,        "setne"         },
00266         { SETNO,        "setno"         },
00267         { SETNP,        "setnp"         },
00268         { SETNS,        "setns"         },
00269         { SETO,         "seto"          },
00270         { SETP,         "setp"          },
00271         { SETS,         "sets"          },
00272         { SGDT,         "sgdt"          },
00273         { SHL,          "shl%"          },
00274         { SHLD,         "shld"          },
00275         { SHR,          "shr%"          },
00276         { SHRD,         "shrd"          },
00277         { SIDT,         "sidt"          },
00278         { SLDT,         "sldt"          },
00279         { SMSW,         "smsw"          },
00280         { STC,          "stc"           },
00281         { STD,          "std"           },
00282         { STI,          "sti"           },
00283         { STOS,         "stos%"         },
00284         { STR,          "str"           },
00285         { SUB,          "sub%"          },
00286         { TEST,         "test%"         },
00287         { VERR,         "verr"          },
00288         { VERW,         "verw"          },
00289         { WAIT,         "wait"          },
00290         { WBINVD,       "wbinvd"        },
00291         { XADD,         "xadd"          },
00292         { XCHG,         "xchg%"         },
00293         { XLAT,         "xlat"          },
00294         { XOR,          "xor%"          },
00295 };
00296 
00297 #define farjmp(o)       ((o) == JMPF || (o) == CALLF)
00298 
00299 static FILE *ef;
00300 static long eline= 1;
00301 static char *efile;
00302 static char *orig_efile;
00303 static char *opcode2name_tab[N_OPCODES];
00304 static enum dialect { ACK, NCC } dialect= ACK;
00305 
00306 static void ack_putchar(int c)
00307 /* LOOK, this programmer checks the return code of putc!  What an idiot, noone
00308  * does that!
00309  */
00310 {
00311         if (putc(c, ef) == EOF) fatal(orig_efile);
00312 }
00313 
00314 static void ack_printf(const char *fmt, ...)
00315 {
00316         va_list ap;
00317 
00318         va_start(ap, fmt);
00319         if (vfprintf(ef, fmt, ap) == EOF) fatal(orig_efile);
00320         va_end(ap);
00321 }
00322 
00323 void ack_emit_init(char *file, const char *banner)
00324 /* Prepare producing an ACK assembly file. */
00325 {
00326         mnemonic_t *mp;
00327 
00328         if (file == nil) {
00329                 file= "stdout";
00330                 ef= stdout;
00331         } else {
00332                 if ((ef= fopen(file, "w")) == nil) fatal(file);
00333         }
00334         orig_efile= file;
00335         efile= file;
00336         ack_printf("! %s", banner);
00337         if (dialect == ACK) {
00338                 /* Declare the four sections used under Minix. */
00339                 ack_printf(
00340         "\n.sect .text; .sect .rom; .sect .data; .sect .bss\n.sect .text");
00341         }
00342 
00343         /* Initialize the opcode to mnemonic translation table. */
00344         for (mp= mnemtab; mp < arraylimit(mnemtab); mp++) {
00345                 assert(opcode2name_tab[mp->opcode] == nil);
00346                 opcode2name_tab[mp->opcode]= mp->name;
00347         }
00348 }
00349 
00350 #define opcode2name(op)         (opcode2name_tab[op] + 0)
00351 
00352 static void ack_put_string(const char *s, size_t n)
00353 /* Emit a string with weird characters quoted. */
00354 {
00355         while (n > 0) {
00356                 int c= *s;
00357 
00358                 if (c < ' ' || c > 0177) {
00359                         ack_printf("\\%03o", c & 0xFF);
00360                 } else
00361                 if (c == '"' || c == '\\') {
00362                         ack_printf("\\%c", c);
00363                 } else {
00364                         ack_putchar(c);
00365                 }
00366                 s++;
00367                 n--;
00368         }
00369 }
00370 
00371 static void ack_put_expression(asm86_t *a, expression_t *e, int deref)
00372 /* Send an expression, i.e. instruction operands, to the output file.  Deref
00373  * is true when the rewrite for the ncc dialect may be made.
00374  */
00375 {
00376         assert(e != nil);
00377 
00378         switch (e->operator) {
00379         case ',':
00380                 if (dialect == NCC && farjmp(a->opcode)) {
00381                         /* ACK jmpf seg:off  ->  NCC jmpf off,seg */
00382                         ack_put_expression(a, e->right, deref);
00383                         ack_printf(", ");
00384                         ack_put_expression(a, e->left, deref);
00385                 } else {
00386                         ack_put_expression(a, e->left, deref);
00387                         ack_printf(farjmp(a->opcode) ? ":" : ", ");
00388                         ack_put_expression(a, e->right, deref);
00389                 }
00390                 break;
00391         case 'O':
00392                 if (deref && a->optype == JUMP) ack_putchar('@');
00393                 if (e->left != nil) ack_put_expression(a, e->left, 0);
00394                 if (e->middle != nil) ack_put_expression(a, e->middle, 0);
00395                 if (e->right != nil) ack_put_expression(a, e->right, 0);
00396                 break;
00397         case '(':
00398                 if (deref && a->optype == JUMP) ack_putchar('@');
00399                 if (!deref) ack_putchar('(');
00400                 ack_put_expression(a, e->middle, 0);
00401                 if (!deref) ack_putchar(')');
00402                 break;
00403         case 'B':
00404                 ack_printf("(%s)", e->name);
00405                 break;
00406         case '1':
00407         case '2':
00408         case '4':
00409         case '8':
00410                 ack_printf((use16() && e->operator == '1')
00411                                 ? "(%s)" : "(%s*%c)", e->name, e->operator);
00412                 break;
00413         case '+':
00414         case '-':
00415         case '~':
00416                 if (e->middle != nil) {
00417                         if (deref && a->optype != JUMP) ack_putchar('#');
00418                         ack_putchar(e->operator);
00419                         ack_put_expression(a, e->middle, 0);
00420                         break;
00421                 }
00422                 /*FALL THROUGH*/
00423         case '*':
00424         case '/':
00425         case '%':
00426         case '&':
00427         case '|':
00428         case '^':
00429         case S_LEFTSHIFT:
00430         case S_RIGHTSHIFT:
00431                 if (deref && a->optype != JUMP) ack_putchar('#');
00432                 ack_put_expression(a, e->left, 0);
00433                 if (e->operator == S_LEFTSHIFT) {
00434                         ack_printf("<<");
00435                 } else
00436                 if (e->operator == S_RIGHTSHIFT) {
00437                         ack_printf(">>");
00438                 } else {
00439                         ack_putchar(e->operator);
00440                 }
00441                 ack_put_expression(a, e->right, 0);
00442                 break;
00443         case '[':
00444                 if (deref && a->optype != JUMP) ack_putchar('#');
00445                 ack_putchar('[');
00446                 ack_put_expression(a, e->middle, 0);
00447                 ack_putchar(']');
00448                 break;
00449         case 'W':
00450                 if (deref && a->optype == JUMP && isregister(e->name))
00451                 {
00452                         ack_printf("(%s)", e->name);
00453                         break;
00454                 }
00455                 if (deref && a->optype != JUMP && !isregister(e->name)) {
00456                         ack_putchar('#');
00457                 }
00458                 ack_printf("%s", e->name);
00459                 break;
00460         case 'S':
00461                 ack_putchar('"');
00462                 ack_put_string(e->name, e->len);
00463                 ack_putchar('"');
00464                 break;
00465         default:
00466                 fprintf(stderr,
00467                 "asmconv: internal error, unknown expression operator '%d'\n",
00468                         e->operator);
00469                 exit(EXIT_FAILURE);
00470         }
00471 }
00472 
00473 void ack_emit_instruction(asm86_t *a)
00474 /* Output one instruction and its operands. */
00475 {
00476         int same= 0;
00477         char *p;
00478         static int high_seg;
00479         int deref;
00480 
00481         if (a == nil) {
00482                 /* Last call */
00483                 ack_putchar('\n');
00484                 return;
00485         }
00486 
00487         /* Make sure the line number of the line to be emitted is ok. */
00488         if ((a->file != efile && strcmp(a->file, efile) != 0)
00489                                 || a->line < eline || a->line > eline+10) {
00490                 ack_putchar('\n');
00491                 ack_printf("# %ld \"%s\"\n", a->line, a->file);
00492                 efile= a->file;
00493                 eline= a->line;
00494         } else {
00495                 if (a->line == eline) {
00496                         ack_printf("; ");
00497                         same= 1;
00498                 }
00499                 while (eline < a->line) {
00500                         ack_putchar('\n');
00501                         eline++;
00502                 }
00503         }
00504 
00505         if (a->opcode == DOT_LABEL) {
00506                 assert(a->args->operator == ':');
00507                 ack_printf("%s:", a->args->name);
00508         } else
00509         if (a->opcode == DOT_EQU) {
00510                 assert(a->args->operator == '=');
00511                 ack_printf("\t%s = ", a->args->name);
00512                 ack_put_expression(a, a->args->middle, 0);
00513         } else
00514         if ((p= opcode2name(a->opcode)) != nil) {
00515                 char *sep= dialect == ACK ? "" : ";";
00516 
00517                 if (!is_pseudo(a->opcode) && !same) ack_putchar('\t');
00518 
00519                 switch (a->rep) {
00520                 case ONCE:      break;
00521                 case REP:       ack_printf("rep");      break;
00522                 case REPE:      ack_printf("repe");     break;
00523                 case REPNE:     ack_printf("repne");    break;
00524                 default:        assert(0);
00525                 }
00526                 if (a->rep != ONCE) {
00527                         ack_printf(dialect == ACK ? " " : "; ");
00528                 }
00529                 switch (a->seg) {
00530                 case DEFSEG:    break;
00531                 case CSEG:      ack_printf("cseg");     break;
00532                 case DSEG:      ack_printf("dseg");     break;
00533                 case ESEG:      ack_printf("eseg");     break;
00534                 case FSEG:      ack_printf("fseg");     break;
00535                 case GSEG:      ack_printf("gseg");     break;
00536                 case SSEG:      ack_printf("sseg");     break;
00537                 default:        assert(0);
00538                 }
00539                 if (a->seg != DEFSEG) {
00540                         ack_printf(dialect == ACK ? " " : "; ");
00541                 }
00542                 if (a->oaz & OPZ) ack_printf(use16() ? "o32 " : "o16 ");
00543                 if (a->oaz & ADZ) ack_printf(use16() ? "a32 " : "a16 ");
00544 
00545                 if (a->opcode == CBW) {
00546                         p= !(a->oaz & OPZ) == use16() ? "cbw" : "cwde";
00547                 }
00548 
00549                 if (a->opcode == CWD) {
00550                         p= !(a->oaz & OPZ) == use16() ? "cwd" : "cdq";
00551                 }
00552 
00553                 if (a->opcode == DOT_COMM && a->args != nil
00554                         && a->args->operator == ','
00555                         && a->args->left->operator == 'W'
00556                 ) {
00557                         ack_printf(".define\t%s; ", a->args->left->name);
00558                 }
00559                 while (*p != 0) {
00560                         if (*p == '%') {
00561                                 if (a->optype == BYTE) ack_putchar('b');
00562                         } else {
00563                                 ack_putchar(*p);
00564                         }
00565                         p++;
00566                 }
00567                 if (a->args != nil) {
00568                         ack_putchar('\t');
00569                         switch (a->opcode) {
00570                         case IN:
00571                         case OUT:
00572                         case INT:
00573                                 deref= 0;
00574                                 break;
00575                         default:
00576                                 deref= (dialect == NCC && a->optype != PSEUDO);
00577                         }
00578                         ack_put_expression(a, a->args, deref);
00579                 }
00580                 if (a->opcode == DOT_USE16) set_use16();
00581                 if (a->opcode == DOT_USE32) set_use32();
00582         } else {
00583                 fprintf(stderr,
00584                         "asmconv: internal error, unknown opcode '%d'\n",
00585                         a->opcode);
00586                 exit(EXIT_FAILURE);
00587         }
00588 }
00589 
00590 /* A few ncc mnemonics are different. */
00591 static mnemonic_t ncc_mnemtab[] = {
00592         { DOT_BSS,      ".bss"          },
00593         { DOT_DATA,     ".data"         },
00594         { DOT_END,      ".end"          },
00595         { DOT_ROM,      ".rom"          },
00596         { DOT_TEXT,     ".text"         },
00597 };
00598 
00599 void ncc_emit_init(char *file, const char *banner)
00600 /* The assembly produced by the Minix ACK ANSI C compiler for the 8086 is
00601  * different from the normal ACK assembly, and different from the old K&R
00602  * assembler.  This brings us endless joy.  (It was supposed to make
00603  * translation of the assembly used by the old K&R assembler easier by
00604  * not deviating too much from that dialect.)
00605  */
00606 {
00607         mnemonic_t *mp;
00608 
00609         dialect= NCC;
00610         ack_emit_init(file, banner);
00611 
00612         /* Replace a few mnemonics. */
00613         for (mp= ncc_mnemtab; mp < arraylimit(ncc_mnemtab); mp++) {
00614                 opcode2name_tab[mp->opcode]= mp->name;
00615         }
00616 }
00617 
00618 void ncc_emit_instruction(asm86_t *a)
00619 {
00620         ack_emit_instruction(a);
00621 }

Generated on Fri Apr 14 22:56:55 2006 for minix by  doxygen 1.4.6