/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef STATE_20060715_H_
#define STATE_20060715_H_

#include "EDBTypes.h"

class QString;

struct State {
public:
	State();
	virtual ~State();

private:
	// not copyable, use to/fromBackup routines
	State(const State &other);
	State &operator=(const State &other);
	
public:
	// what an FPU register looks like	
	struct i387Register {
	public:
		i387Register();
		i387Register(const i387Register &other);
		i387Register &operator=(const i387Register &other);
	public:
		double toDouble() const;
	public:
		bool operator==(const i387Register &other) const;
		bool operator!=(const i387Register &other) const;
	public:
		uint8_t raw[10];
	};

public:
	// the actual state storage
	edb::reg_t ebx;
	edb::reg_t ecx;
	edb::reg_t edx;
	edb::reg_t esi;
	edb::reg_t edi;
	edb::reg_t ebp;
	edb::reg_t eax;
	edb::reg_t esp;
	union { edb::reg_t _cs; uint16_t cs; };
	union { edb::reg_t _ds; uint16_t ds; };
	union { edb::reg_t _es; uint16_t es; };
	union { edb::reg_t _fs; uint16_t fs; };
	union { edb::reg_t _gs; uint16_t gs; };
	union { edb::reg_t _ss; uint16_t ss; };
	union { edb::reg_t eip; uint16_t ip; };
	union { edb::reg_t eflags; uint16_t flags; };
	edb::reg_t orig_eax;
	
	i387Register st[8];
	
public:
	virtual edb::address_t instructionPointer() const;
	virtual edb::address_t stackPointer() const;
	virtual void frombackup(const State &backup);
	virtual void toBackup(State &backup) const;
	virtual edb::reg_t value(const QString &reg, bool *ok = 0) const;
	virtual void clear();
	
public:
	enum {		
		// groups, these catagories should remain as portable as possible
		REG_GPR		= 0x0001,
		REG_IP		= 0x0002,
		REG_SEG		= 0x0004,
		REG_COND	= 0x0008,
		REG_FPU		= 0x0010,
		REG_ANY		= -1
	};
};

#endif
