#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct EXT__ARCH *settings; /* might come in handy */

void ext_arch_init( void *param) {
   settings = (struct EXT__ARCH *)param;

   if (! settings) return;

   /* Init register info */
   settings->sz_regtable = 1;
   settings->reg_table = calloc( sizeof(struct REGTBL_ENTRY), 1);
   settings->reg_storage = calloc(32, 1);
   AddRegTableEntry( 0, "eax", 4);

   /* set CPU specific information */
   settings->sz_addr = 4;
   settings->sz_oper = 4;
   settings->SP = 4 + REG_DWORD_OFFSET;
   settings->IP = REG_EIP_INDEX;
   settings->sz_inst = 0;
   settings->sz_byte = 8;
   settings->sz_word = 2;
   settings->sz_dword = 4;
   settings->endian = LITTLE_ENDIAN_ORD;
   return;
}
   
void ext_arch_cleanup( void ) {
   if (settings->reg_table) free(settings->reg_table);
   if (settings->sz_regtable) settings->sz_regtable = 0;
   if (settings->reg_storage) free(settings->reg_storage);
   return;
}

/* --- Exported Information Routines -------------------------------------*/
/* These are used to pass information about the platform to the higher-level
 * disassembler  -- there will probably be more added when additional CPUs
 * are supported */
int get_prologue(struct code **table){
   /* This function and the following are kind of tricky. They fill 'table'
    * with an array of CODE structs; within the array, each 'prologue' is
    * represented by a series of CODE structs followed by a NULL code struct.
    * The number returned is the number of prologues. See the function 
    * recognition pass for details on how to use these routines */
   struct code *t; 
   int num = 2;
   int i, j;
   
   t = (struct code *) calloc( sizeof( struct code ), 6);
   /* ------------------------------ customize this part only !! */
   /* prolog1:  push esp
    *           mov  ebp, esp
    *           sub  esp, ??? */
   strcpy( t[0].mnemonic, "push");
   t[0].dest = 5 + REG_DWORD_OFFSET;
   strcpy( t[1].mnemonic, "mov");
   t[1].dest = 5 + REG_DWORD_OFFSET;
   t[1].src= 4 + REG_DWORD_OFFSET;
   strcpy( t[2].mnemonic, "sub");
   t[2].dest = 4 + REG_DWORD_OFFSET;
   /* prolog2: enter */ 
   strcpy( t[4].mnemonic, "enter");
   /* ------------------------------- end customize-part */

   *table = t;
   return(num);
}

int get_epilogue(struct code **table){
   struct code *t; 
   int num = 2;
   int i, j;
   
   /* calloc room for sequences of code structures */
   t = (struct code *) calloc( sizeof( struct code ), 4);
   /* ------------------------------ customize this part only !! */
   /* epilog1:  ret */
   strcpy( t[0].mnemonic, "ret");
   /* epilog2: retf */ 
   strcpy( t[2].mnemonic, "retf");
   /* ------------------------------- end customize-part */

   *table = t;
   return(num);
}


/* get the effects on registers of a specified instruction */
int get_reg_effect( char *mnemonic, struct code_effect *e){
   /* the mnemonic is used to determine the effects of instructions
    * which are predetermined, e.g. a call or a push affecting the 
    * stack pointer. All effects dependent on operands are managed
    * by the calling program */
   return(1);
}
/* generate intermediate code for a function */
int gen_int( int func_id ) {
   return(1);
}
/* ------------ Disassembly Routines ----------------------------------- */

/* this function is called by the controlling disassembler, so its name and
 * calling convention cannot be changed */
int disasm_addr( BYTE *buf, BYTE tbl, struct code *c, long rva){
    /*   buf points to the loc of the current opcode (start of the 
    *        intruction) in the instruction stream. The instruction stream
    *        is assumed to be a buffer ob bytes read directly from the file
    *        for the purpose of disassembly; a mmapped file is ideal for 
    *        this.
    *    tbl indicates which table to lookup this opcode in; 0 is the main
    *        opcode table and is the only table that should be referenced by
    *        a non-recursive call.
    *    c   points to a code structure which will be filled by InstDecode
    *    rva is the virtual address of the current instruction
    *    returns the size of the decoded instruction in bytes */
   int size = 0;

   /* decode instruction here and return size */

   return(size);
}
