Logo Search packages:      
Sourcecode: faucc version File versions

test-i386-add.c

/* $Id: test-i386-add.c,v 1.2 2009-01-27 15:58:54 potyra Exp $ 
 *
 * Copyright (C) 2008-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */
#define addr_t uint32_t

#ifndef __CHIP_H__
#define __CHIP_H__

#include <inttypes.h>

/******************************************************************************/

#define true (!false)
#define false (0)

typedef int bool;

/******************************************************************************/

extern uint8_t get_uint8(void);
extern uint16_t get_uint16(void);
extern uint32_t get_uint32(void);
extern uint64_t get_uint64(void);

/******************************************************************************/

extern uint8_t load_uint8(addr_t addr);
extern uint16_t load_uint16(addr_t addr);
extern uint32_t load_uint32(addr_t addr);
extern uint64_t load_uint64(addr_t addr);

/******************************************************************************/

extern void store_uint8(uint8_t value, addr_t addr);
extern void store_uint16(uint16_t value, addr_t addr);
extern void store_uint32(uint32_t value, addr_t addr);
extern void store_uint64(uint64_t value, addr_t addr);

/******************************************************************************/

typedef struct _bit_t *bit_t;

extern bool bit_get(bit_t);
extern void bit_set(bit_t, bool value);
extern void bit_unset(bit_t);

/******************************************************************************/

/* only use at points never reached! */
extern __attribute__((__noreturn__)) void error(const char *file, int line);

#define ERROR() error(__FILE__, __LINE__)

/******************************************************************************/

#endif /* __CHIP_H__ */

/******************************************************************************/

enum operand_t {
      OPERAND_EAX = 0x0,
      OPERAND_ECX = 0x1,
      OPERAND_EDX = 0x2,
      OPERAND_EBX = 0x3,
      OPERAND_ESP = 0x4,
      OPERAND_EBP = 0x5,
      OPERAND_ESI = 0x6,
      OPERAND_EDI = 0x7,
      OPERAND_IMMEDIATE,
      OPERAND_ADDRESS,
      OPERAND_CS,
      OPERAND_SS,
      OPERAND_DS,
      OPERAND_ES,
      OPERAND_FS,
      OPERAND_GS
};

enum operand_size_t {
      OPERAND_SIZE_1 = 1,
      OPERAND_SIZE_2 = 2,
      OPERAND_SIZE_4 = 4
};

enum prefix_lock_repeat_t {
      PREFIX_LR_NONE,
      PREFIX_LR_LOCK,
      PREFIX_LR_REPNZ,
      PREFIX_LR_REPZ
};

enum prefix_segment_override_t {
      PREFIX_SO_NONE,
      PREFIX_SO_CS,
      PREFIX_SO_SS,
      PREFIX_SO_DS,
      PREFIX_SO_ES,
      PREFIX_SO_FS,
      PREFIX_SO_GS
};

/******************************************************************************
 *
 * Global variables (CPU State)
 *
 ******************************************************************************/

// General-purpose data registers
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;

// Segment Registers
uint16_t cs; // Code Segment
uint16_t ss; // Stack Segment
uint16_t ds; // Data Segment
uint16_t es; // Data Segment
uint16_t fs; // Data Segment
uint16_t gs; // Data Segment

// Status and Control Registers
//uint32_t EFLAGS;
//uint32_t EIP;

// EFLAGS (Status Flags)
bit_t cf; // Carry Flag
bit_t pf; // Parity Flag
bit_t af; // Auxiliary Carry Flag
bit_t zf; // Zero Flag
bit_t sf; // Sign Flag
bit_t of; // Overflow Flag

/******************************************************************************/

static inline uint32_t get_uint(enum operand_size_t size) {
      uint32_t value;

      switch (size) {
            case OPERAND_SIZE_1:
                  value = get_uint8();
                  break;
            case OPERAND_SIZE_2:
                  value = get_uint16();
                  break;
            case OPERAND_SIZE_4:
                  value = get_uint32();
                  break;
            // no default!
      }
      return value;
}

/******************************************************************************/

static inline uint32_t mask(uint32_t t, enum operand_size_t size) {
      uint32_t value;

      switch (size) {
            case OPERAND_SIZE_1:
                  value = t & 0xff;
                  break;
            case OPERAND_SIZE_2:
                  value = t & 0xffff;
                  break;
            case OPERAND_SIZE_4:
                  value = t & 0xffffffff;
                  break;
            // no default!
      }
      return value;
}

/******************************************************************************/

static inline void store(uint32_t t,
                   enum operand_t operand,
                   enum operand_size_t size,
                   uint32_t addr) {
      switch (operand) {
            case OPERAND_EAX:
                  eax = mask(t, size);
                  break;
            case OPERAND_ECX:
                  ecx = mask(t, size);
                  break;
            case OPERAND_EDX:
                  edx = mask(t, size);
                  break;
            case OPERAND_EBX:
                  ebx = mask(t, size);
                  break;
            case OPERAND_ESP:
                  esp = mask(t, size);
                  break;
            case OPERAND_EBP:
                  ebp = mask(t, size);
                  break;
            case OPERAND_ESI:
                  esi = mask(t, size);
                  break;
            case OPERAND_EDI:
                  edi = mask(t, size);
                  break;
            case OPERAND_IMMEDIATE:
                  ERROR();
                  break;
            case OPERAND_ADDRESS:
                  switch (size) {
                        case OPERAND_SIZE_1:
                              store_uint8(t, addr);
                              break;
                        case OPERAND_SIZE_2:
                              store_uint16(t, addr);
                              break;
                        case OPERAND_SIZE_4:
                              store_uint32(t, addr);
                              break;
                        // no default!
                  }
                  break;
            case OPERAND_CS:
                  cs = mask(t, size);
                  break;
            case OPERAND_SS:
                  ss = mask(t, size);
                  break;
            case OPERAND_DS:
                  ds = mask(t, size);
                  break;
            case OPERAND_ES:
                  es = mask(t, size);
                  break;
            case OPERAND_FS:
                  fs = mask(t, size);
                  break;
            case OPERAND_GS:
                  gs = mask(t, size);
                  break;
            // no default!
      }
}

static inline uint32_t load(enum operand_t operand,
                      enum operand_size_t size,
                      uint32_t addr) {
      uint32_t value;

      switch (operand) {
            case OPERAND_EAX:
                  value = mask(eax, size);
                  break;
            case OPERAND_ECX:
                  value = mask(ecx, size);
                  break;
            case OPERAND_EDX:
                  value = mask(edx, size);
                  break;
            case OPERAND_EBX:
                  value = mask(ebx, size);
                  break;
            case OPERAND_ESP:
                  value = mask(esp, size);
                  break;
            case OPERAND_EBP:
                  value = mask(ebp, size);
                  break;
            case OPERAND_ESI:
                  value = mask(esi, size);
                  break;
            case OPERAND_EDI:
                  value = mask(edi, size);
                  break;
            case OPERAND_IMMEDIATE:
                  value = get_uint(size);
                  break;
            case OPERAND_ADDRESS:
                  switch (size) {
                        case OPERAND_SIZE_1:
                              value = load_uint8(addr);
                              break;
                        case OPERAND_SIZE_2:
                              value = load_uint16(addr);
                              break;
                        case OPERAND_SIZE_4:
                              value = load_uint32(addr);
                              break;
                        // no default!
                  }
                  break;
            case OPERAND_CS:
                  value = mask(cs, size);
                  break;
            case OPERAND_SS:
                  value = mask(ss, size);
                  break;
            case OPERAND_DS:
                  value = mask(ds, size);
                  break;
            case OPERAND_ES:
                  value = mask(es, size);
                  break;
            case OPERAND_FS:
                  value = mask(fs, size);
                  break;
            case OPERAND_GS:
                  value = mask(gs, size);
                  break;
            // no default!
      }
      return value;
}

/******************************************************************************
 *
 * SF - Sign flag
 *
 * Set equal to the most-significant bit of the result, which is the sign bit
 * of a signed integer. (0 indicates a positive value and 1 indicates a negative
 * value.)
 *
 ******************************************************************************/

static inline void update_sf(uint32_t t, enum operand_size_t size) {
      switch (size) {
            case OPERAND_SIZE_1:
                  bit_set(sf, t >> 7);
                  break;
            case OPERAND_SIZE_2:
                  bit_set(sf, t >> 15);
                  break;
            case OPERAND_SIZE_4:
                  bit_set(sf, t >> 31);
                  break;
            // no default!
      }
}

/******************************************************************************
 *
 * ZF - Zero flag
 *
 * Set if the result is zero; cleared otherwise.
 *
 ******************************************************************************/

static inline void update_zf(uint32_t t) {
      bit_set(zf, t == 0);
}

/******************************************************************************
 *
 * PF - Parity flag
 *
 * Set if the least-significant byte of the result contains an even number
 * of 1 bits; cleared otherwise.
 *
 ******************************************************************************/

static inline void update_pf(uint32_t t) {
      static const uint8_t parity_table[256] = {
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0x00 - 0x0f
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0x10 - 0x1f
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0x20 - 0x2f
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0x30 - 0x3f
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0x40 - 0x4f
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0x50 - 0x5f
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0x60 - 0x6f
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0x70 - 0x7f
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0x80 - 0x8f
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0x90 - 0x9f
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0xa0 - 0xaf
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0xb0 - 0xbf
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0xc0 - 0xcf
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0xd0 - 0xdf
            0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, // 0xe0 - 0xef
            1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, // 0xf0 - 0xff
      };
      bit_set(pf, parity_table[(uint8_t) t]);
}

/******************************************************************************
 *
 * 'Result' - Flags
 *
 * Update SF, ZF and PF.
 *
 ******************************************************************************/

static inline void update_sf_zf_pf(uint32_t t, enum operand_size_t size) {
      update_sf(t, size);
      update_zf(t);
      update_pf(t);
}

/******************************************************************************
 *
 * Arithmetic and Logic Generator Functions
 *
 ******************************************************************************/

/* Add */
static inline void add(enum operand_t operand_a, enum operand_size_t size_a, enum operand_t operand_b, enum operand_size_t size_b, uint32_t addr) {
      uint32_t t0, t1, t2;

      t1 = load(operand_a, size_a, addr);
      t2 = load(operand_b, size_b, addr);
      t0 = mask(t1 + t2, size_a);
      store(t0, operand_a, size_a, addr);
      update_sf_zf_pf(t0, size_a);
      bit_set(cf, t0 < t1);
      bit_set(of, (t1 ^ t2 ^ -1) & (t1 ^ t0));
      bit_set(af, (t1 ^ t2 ^ t0) & 0x10);
}

/******************************************************************************/

void add_eax_4_eax_4(uint32_t addr) {
      add(OPERAND_EAX, OPERAND_SIZE_4, OPERAND_EAX, OPERAND_SIZE_4, addr);
}

void add_edx_2_ebx_2(uint32_t addr) {
      add(OPERAND_EDX, OPERAND_SIZE_2, OPERAND_EBX, OPERAND_SIZE_2, addr);
}

void add_ebx_4_addr_4(uint32_t addr) {
      add(OPERAND_EBX, OPERAND_SIZE_4, OPERAND_ADDRESS, OPERAND_SIZE_4, addr);
}

void add_ecx_4_imm_4(uint32_t addr) {
      add(OPERAND_ECX, OPERAND_SIZE_4, OPERAND_IMMEDIATE, OPERAND_SIZE_4, addr);
}

void add_eax_4_imm_1(uint32_t addr) {
      add(OPERAND_EAX, OPERAND_SIZE_4, OPERAND_IMMEDIATE, OPERAND_SIZE_1, addr);
}


Generated by  Doxygen 1.6.0   Back to index