Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

ac_decoder.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 
00003 /*  Generic decoder for arquitectures described in ArchC
00004     Copyright (C) 2002-2004  The ArchC Team
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library 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 GNU
00014     Lesser General Public License for more details.
00015 */
00016 
00017 /********************************************************/
00018 /* The ArchC Decoder Generator                          */
00019 /* Author: Marcus Bartholomeu and Sandro Rigo           */
00020 /* Contributor: Marcelo de Almeida Oliveira             */
00021 /*                                                      */
00022 /* The ArchC Team                                       */
00023 /* Computer Systems Laboratory (LSC)                    */
00024 /* IC-UNICAMP                                           */
00025 /* http://www.lsc.ic.unicamp.br                         */
00026 /********************************************************/
00028 
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include "ac_decoder.h"
00039 
00040 
00042 int ExpandInstrBuffer(int index);
00043 
00044 
00045 unsigned long long GetBits(unsigned char *buffer, int *quant, int last, int quantity, int sign)
00046 {
00048 #define BUFFER(index) ((index<*quant) ? (buffer[index]) : (*quant=ExpandInstrBuffer(index),buffer[index]))
00049 
00050   int first = last - (quantity-1);
00051   int index;
00052   unsigned long long value;
00053 
00054   //Locate and read the first byte
00055   index = first/8; first %= 8;
00056   value = BUFFER(index);
00057 
00058   //Erase bits before "first"
00059   value &= 0xFF >> first;
00060 
00061   //Calculate new last
00062   last = first + (quantity-1);
00063 
00064   //If the last is in this byte
00065   if (last < 8) {
00066 
00067     //Shift right to get value
00068     value >>= 8 - (last+1);
00069   }
00070 
00071   //Else the last is not in this byte
00072   else {
00073 
00074     //Next word
00075     index++;
00076     last -= 8;
00077 
00078     //Append bytes to value, until the last is in this byte
00079     while (last >= 8) {
00080       value <<= 8;
00081       value |= BUFFER(index);
00082 
00083       //Next word
00084       index++;
00085       last -= 8;
00086     }
00087 
00088     //Copy the last bits (don't copy a byte! that could overflow)
00089     value <<= last+1;
00090     value |= BUFFER(index) >> (8 - (last+1));
00091   }
00092 
00093   //If signed, sign extend if necessary
00094   if (sign && ( value >= (1 << (quantity-1)) ))
00095     value |= (~0LL) << quantity;
00096 
00097   return value;
00098 #undef BUFFER
00099 }
00100 
00101 
00106 char *NewString(const char *s)
00107 {
00108   char *returnValue = (char *) malloc(strlen(s) + 1);
00109   strcpy(returnValue, s);
00110 
00111   return returnValue;
00112 }
00113 
00114 
00115 void ShowDecField(ac_dec_field *f)
00116 {
00117   while (f) {
00118     printf("\tac_dec_field\n\t  Name : %s\n\t  Size : %d\n\t  First: %d\n\t  ID   : %d\n\t  Value: %ld\n",
00119            f -> name, f -> size, f -> first_bit, f -> id, f -> val);
00120     f = f -> next;
00121   }
00122 }
00123 
00124 
00125 void ShowDecFormat(ac_dec_format *f)
00126 {
00127   while (f) {
00128     printf("ac_dec_format\nName: %s\nFields:\n", f -> name);
00129     ShowDecField(f -> fields);
00130     f = f -> next;
00131   }
00132 }
00133 
00134 
00135 void ShowDecodeList(ac_dec_list *l)
00136 {
00137   while (l) {
00138     printf("\tac_dec_list\n\t  Name : %s\n\t  Value: %d\n", l -> name, l -> value);
00139     l = l -> next;
00140   }
00141 }
00142 
00143 
00144 void ShowDecInstr(ac_dec_instr *i)
00145 {
00146   while (i) {
00147     printf("ac_dec_instr\nName    : %s\nMnemonic: %s\nASM     : %s\nFormat  : %s\nDecode List:\n",
00148            i -> name, i -> mnemonic, i -> asm_str, i -> format);
00149     ShowDecodeList(i -> dec_list);
00150     i = i -> next;
00151   }
00152 }
00153 
00154 
00155 void ShowDecoder(ac_decoder *d, unsigned level)
00156 {
00157   char *ident = (char *) malloc(level * 4 + 1);
00158   unsigned counter;
00159 
00160   for (counter = 0; counter < level * 4; counter ++)
00161     ident[counter] = ' ';
00162 
00163   ident[level * 4] = '\0';
00164 
00165   while (d) {
00166     printf("%sac_decoder:\n", ident);
00167     printf("%s Field:\n", ident);
00168     printf("%s  Name: %s\n%s  Val : %d\n", ident, d -> check -> name, ident, d -> check -> value);
00169     if (d -> found) {
00170       printf("%s Instruction Found:\n", ident);
00171       printf("%s  Name    : %s\n%s  Mnemonic: %s\n", ident, d -> found -> name, ident, d -> found -> mnemonic);
00172     }
00173     else
00174       ShowDecoder(d -> subcheck, level + 1);
00175 
00176     d = d -> next;
00177   }
00178 
00179   free(ident);
00180 }
00181 
00182 
00183 void MemoryError(char *fileName, long lineNumber, char *functionName)
00184 {
00185   fprintf(stderr, "%s: %ld: Not enough memory at %s", fileName, lineNumber, functionName);
00186   exit(1);
00187 }
00188 
00189 
00190 void ShowError(char *msg)
00191 {
00192   fprintf(stderr, msg);
00193   exit(1);
00194 }
00195 
00196 
00198 int CompareFields(const void *p1, const void *p2)
00199 {
00200   const ac_dec_field *f1 = (const ac_dec_field *) p1, *f2 = (const ac_dec_field *) p2;
00201 
00202   return strcmp(f1 -> name, f2 -> name);
00203 }
00204 
00205 
00206 /* Fields which have the same name, should have the same position inside the instruction
00207    \return 0 if fields have the same name but different position, -1 if fields are equal, 1 otherwise
00208 */
00209 
00210 int CheckFields(const ac_dec_field *f1, const ac_dec_field *f2)
00211 {
00212   if (!strcmp(f1 -> name, f2 -> name)) {
00213     if (strcmp(f1 -> name, "0")) {  
00214       if ((f1 -> size != f2 -> size) || (f1 -> first_bit != f2 -> first_bit)) {
00215         ShowError("Fields with the same name should have the same position.\n");
00216         return 0;
00217       }
00218     }
00219     else
00220       return 1;
00221     
00222     return -1;
00223   }
00224   return 1;
00225 }
00226 
00227 
00228 /* ac_dec_field *CopyDecField(ac_dec_field *dst, const ac_dec_field *src) */
00229 /* { */
00230 /*   *dst = *src; */
00231 /*   dst -> name = NewString(src -> name); */
00232 /* } */
00233 
00234 
00235 /* ac_dec_field *NewDecField(ac_dec_field *p) */
00236 /* { */
00237 /*   ac_dec_field *f = (ac_dec_field *) malloc(sizeof(ac_dec_field)); */
00238 
00239 /*   CopyDecField(f, p); */
00240 /*   f -> next = NULL; */
00241 /* } */
00242 
00243 
00244 void FreeDecField(ac_dec_field *f)
00245 {
00246   free(f -> name);
00247   free(f);
00248 }
00249 
00250 
00251 ac_dec_field *FindDecField(ac_dec_field *fields, char *name)
00252 {
00253   while (fields) {
00254     if (!strcmp(fields -> name, name))
00255       return fields;
00256     
00257     fields = fields -> next;
00258   }
00259 
00260   return NULL;
00261 }
00262 
00263 
00264 ac_dec_field *PutIDs(ac_dec_format *formats, unsigned nFields)
00265      /* TODO:
00266         - porque o indice e o id não são iguais? (poderia pegar o nome pelo id) (id 0 reservado)
00267         - porque não muda o id na mesma estrutura recebida?
00268         - nFields é na verdade o limit!!! (== id de maior valor) (ao alocar, nFields+1, pois tem o 0)
00269       */
00270 {
00271   ac_dec_field *fields, *tmp;
00272   ac_dec_format *f = formats;
00273   unsigned limit = 0, index, result;
00274   char found;
00275 
00276   // Allocates memory
00277   fields = (ac_dec_field *) malloc(nFields * sizeof(ac_dec_field));
00278 
00279   // Creates a vector with unique occurrences of all fields
00280   while (f) {
00281     tmp = f -> fields;
00282     while (tmp) {
00283       found = 0;
00284       for (index = 0; index < limit; index ++) {
00285         result = CheckFields(&(fields[index]), tmp);
00286         if (result == -1) {
00287           found = 1;
00288           tmp -> id = fields[index].id;
00289           break;
00290         }
00291       }
00292       
00293       if (!found) {
00294         tmp -> id = limit + 1;
00295         fields[limit] = *tmp;
00296         fields[limit].name = NewString(tmp -> name);
00297         
00298         if (limit != 0)
00299           fields[limit - 1].next = &(fields[limit]);
00300         
00301         fields[limit++].next = NULL;
00302       }
00303       
00304       tmp = tmp -> next;
00305     }
00306     f = f -> next;
00307   }
00308 
00309   return fields;
00310 }
00311 
00312 
00313 ac_decoder *AddToDecoder(ac_decoder *decoder, ac_dec_instr *instruction, ac_dec_field *fields)
00314 {
00315   ac_decoder *d = decoder, *base = decoder;
00316   //ac_dec_field *f;
00317   ac_dec_list *l = instruction -> dec_list;
00318   //enum {IncludeSubCheck, IncludeNext} action;
00319   
00320   if (l == NULL) {
00321     fprintf(stderr, "Error: Instruction %s doesn't have a decode list.\n", instruction -> name);
00322     exit(1);
00323   }
00324 
00325   if (d == NULL) {
00326     base = d = (ac_decoder *) malloc(sizeof(ac_decoder));
00327     d -> check = (ac_dec_list *) malloc(sizeof(ac_dec_list));
00328     d -> check -> name = NewString(l -> name);
00329     d -> check -> value = l -> value;
00330     d -> found = NULL;
00331     d -> subcheck = NULL;
00332     d -> next = NULL;
00333   }
00334     
00335   while (l) {
00336     // Same field and same value to check
00337     if ((!strcmp(d -> check -> name, l -> name)) && (d -> check -> value == l -> value))
00338       if (l -> next == NULL) {            // This is the last check
00339         d -> found = instruction;
00340         l = l -> next;
00341       }
00342       else {
00343         l = l -> next;
00344         if (d -> subcheck != NULL)        // Include in subcheck
00345           d = d -> subcheck;
00346         else {
00347           d -> subcheck = (ac_decoder *) malloc(sizeof(ac_decoder));
00348           d = d -> subcheck;
00349           d -> check = (ac_dec_list *) malloc(sizeof(ac_dec_list));
00350           d -> check -> name = NewString(l -> name);
00351           d -> check -> value = l -> value;
00352           d -> found = NULL;
00353           d -> subcheck = NULL;
00354           d -> next = NULL;
00355         }
00356       }
00357     else {
00358       if (d -> next != NULL)
00359         d = d -> next;
00360       else {
00361         d -> next = (ac_decoder *) malloc(sizeof(ac_decoder));
00362         d = d -> next;
00363         d -> check = (ac_dec_list *) malloc(sizeof(ac_dec_list));
00364         d -> check -> name = NewString(l -> name);
00365         d -> check -> value = l -> value;
00366         d -> found = NULL;
00367         d -> subcheck = NULL;
00368         d -> next = NULL;
00369       }
00370     }
00371   }
00372             
00373   d -> found = instruction;
00374   d -> subcheck = NULL;
00375 
00376   return base;
00377 }
00378 
00379 
00380 ac_decoder_full *CreateDecoder(ac_dec_format *formats, ac_dec_instr *instructions)
00381 {
00382   ac_dec_field *field, *allFields;
00383   ac_dec_format *format = formats;
00384   //ac_dec_list *list;
00385   ac_dec_instr *instr = instructions;
00386   ac_decoder *dec;
00387   ac_decoder_full *full;
00388   unsigned nFields = 0, nFormats = 0;
00389 
00390   while (format) {
00391     int format_size = 0;
00392     nFormats ++;
00393     field = format -> fields;
00394     while (field) {
00395       format_size += field->size;
00396       nFields++;
00397       field = field -> next;
00398     }
00399     format->size = format_size;
00400     format = format -> next;
00401   }
00402   nFields++;
00403   allFields = PutIDs(formats, nFields);
00404 
00405   dec = NULL;
00406 
00407   while (instr) {
00408     dec = AddToDecoder(dec, instr, allFields);
00409     instr->size = FindFormat(formats, instr->format)->size / 8;  //bits to bytes
00410     instr = instr -> next;
00411   }
00412 
00413   full = malloc(sizeof(ac_decoder_full));
00414 
00415   full -> decoder = dec;
00416   full -> formats = formats;
00417   full -> fields = allFields;
00418   full -> instructions = instructions;
00419   full -> nFields = nFields;
00420   
00421   return full;
00422 }
00423 
00424 
00425 ac_dec_instr *FindInstruction(ac_decoder_full *decoder, unsigned char *buffer, int quant)
00426 {
00427   ac_decoder *d = decoder -> decoder;
00428   //ac_dec_list *check;
00429   ac_dec_field *field = 0;
00430   long long field_value;
00431   //char byte;
00432 
00433   ac_decoder *chosenPath[64]; // usar uma constante = MAX_DECODER_DEPTH
00434   int chosenPathPos = 0;
00435   chosenPath[chosenPathPos] = d;
00436 
00437   while (d) {
00438     if (!field) {
00439       field = FindDecField(decoder -> fields, d -> check -> name);
00440       field_value = GetBits(buffer, &quant, field -> first_bit, field -> size, field -> sign);
00441     }
00442 
00443     //fprintf(stderr, "Decoder - FieldName: %s ValueRequired: %d ValueFound: %d\n",
00444     //        d -> check -> name, d -> check -> value, field_value);
00445 
00446     if (field_value == d -> check -> value) {
00447       if (d -> found) {
00448         //fprintf(stderr, "Instruction %s has been found.\n", d -> found -> name);
00449         return d -> found;
00450       } else {
00451         //fprintf(stderr, "Following d -> subcheck branch in the decoder tree. \n");
00452         chosenPath[++chosenPathPos] = d -> subcheck;
00453         d = d -> subcheck;
00454         field = 0;
00455       }
00456     } else {
00457       //fprintf(stderr, "Following d->next branch in the decoder tree. \n");
00458       chosenPath[chosenPathPos] = d -> next;
00459       d = d -> next;
00460       if (d && strcmp(d->check->name, field->name) != 0)
00461         field=0;
00462     }
00463 
00464     while ((d == NULL) && (chosenPathPos > 0)) {
00465       //fprintf(stderr, "Backtracking in the decoder tree.\n");
00466       d = chosenPath[--chosenPathPos];
00467       d = d -> next;
00468       if (d && strcmp(d -> check -> name, field -> name) != 0)
00469         field = 0;
00470     }
00471   }
00472 
00473   return NULL;
00474 }
00475 
00476 
00477 ac_dec_format *FindFormat(ac_dec_format *formats, char *name)
00478 {
00479   ac_dec_format *format = formats;
00480 
00481   while(format && (strcmp(format -> name, name) != 0)) {
00482     format = format -> next;
00483   }
00484   if (!format) {
00485     fprintf(stderr, "Invalid format name %s.\n", name);
00486     exit(1);
00487   }
00488   return format;
00489 }
00490 
00491 
00492 ac_dec_instr *GetInstrByID(ac_dec_instr *instr, int id)
00493 {
00494   for (; instr && instr->id != id;) {
00495     instr = instr->next;
00496   }
00497   if (!instr) {
00498     fprintf(stderr, "Invalid instruction ID %d.\n", id);
00499     exit(1);
00500   }
00501   return instr;
00502 }
00503 
00504 
00505 unsigned *DecodeAsInstruction(ac_decoder_full * decoder, ac_dec_instr *instruction, unsigned char *buffer, int quant)
00506 {
00507   static unsigned *fields = 0;
00508   unsigned counter;
00509   ac_dec_field *field;
00510   //ac_dec_list *list = instruction -> dec_list;
00511   ac_dec_field *list ;
00512 
00513   ac_dec_format *format;
00514 
00516   if (!fields) fields = (unsigned *) malloc(sizeof(unsigned) * decoder -> nFields);
00517 
00519   format = FindFormat(decoder->formats, instruction->format);
00520   
00522   list = format -> fields;
00523 
00524   for (counter = 1; counter < decoder -> nFields; counter ++)
00525     fields[counter] = 0;
00526 
00527   while (list) {
00528     field = FindDecField(decoder -> fields, list -> name);
00529     if (!field) {
00530       fprintf(stderr, "Invalid field name %s.\n", list -> name);
00531       exit(1);
00532     }
00533     fields[field -> id] = GetBits(buffer, &quant, field -> first_bit, field -> size, field -> sign);
00534     list = list -> next;
00535   }
00536 
00537   fields[0] = instruction -> id;
00538   return fields;
00539 }
00540 
00541 
00542 unsigned *Decode(ac_decoder_full *decoder, unsigned char *buffer, int quant)
00543 {
00544   ac_dec_instr *instruction;
00545   
00546   instruction = FindInstruction(decoder, buffer, quant);
00547   
00548   if (instruction != NULL) {
00549     return DecodeAsInstruction(decoder, instruction, buffer, quant);
00550   }
00551 
00552   return NULL;
00553 }

Generated on Thu Jun 24 08:30:05 2004 for ArchC by doxygen 1.3.4