1 /*
2  *  cHeadCPU.h
3  *  Avida
4  *
5  *  Called "head_cpu.hh" prior to 11/30/05.
6  *  Copyright 1999-2011 Michigan State University. All rights reserved.
7  *  Copyright 1999-2003 California Institute of Technology.
8  *
9  *
10  *  This file is part of Avida.
11  *
12  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
13  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
14  *
15  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
19  *  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef cHeadCPU_h
24 #define cHeadCPU_h
25 
26 #include "avida/Avida.h"
27 
28 #include "cCPUMemory.h"
29 #include "cHardwareBase.h"
30 #include "cInstSet.h"
31 
32 /**
33  * The cHeadCPU class contains a pointer to locations in memory for a CPU.
34  **/
35 
36 namespace Avida {
37   class Sequence;
38 };
39 class cCodeLabel;
40 class cInstruction;
41 class cString;
42 
43 using namespace Avida;
44 
45 
46 class cHeadCPU
47 {
48 protected:
49   cHardwareBase* m_hardware;
50   int m_position;
51   int m_mem_space;
52   int m_cached_ms;
53   cCPUMemory* m_memory;
54 
55   void fullAdjust(int mem_size = -1);
56 
57   int FindLabel_Forward(const cCodeLabel& search_label, const Sequence& search_mem, int pos);
58   int FindLabel_Backward(const cCodeLabel& search_label, const Sequence& search_mem, int pos);
59 
60 
61 public:
62   inline cHeadCPU(cHardwareBase* hw = NULL, int pos = 0, int ms = 0);
63   inline cHeadCPU(const cHeadCPU& in_cpu_head);
~cHeadCPU()64   ~cHeadCPU() { ; }
65 
GetMemory()66   inline const cCPUMemory& GetMemory() const { return *m_memory; }
GetMemory()67   inline cCPUMemory& GetMemory() { return *m_memory; }
GetMemSize()68   inline int GetMemSize() const { return m_memory->GetSize(); }
69 
Adjust()70   inline void Adjust() { if (m_mem_space != m_cached_ms || m_position < 0 || m_position >= GetMemSize()) fullAdjust(); }
71   inline void Reset(cHardwareBase* hw, int ms = 0) { m_hardware = hw; m_position = 0; m_mem_space = ms; if (hw) Adjust(); }
72 
GetMemSpace()73   inline int GetMemSpace() const { return m_mem_space; }
GetPosition()74   inline int GetPosition() const { return m_position; }
GetFullLocation()75   inline int GetFullLocation() const { return (m_position & 0xFFFFFF) | (m_mem_space << 24); }
76 
77   inline void Set(int pos, int ms = 0) { m_position = pos; m_mem_space = ms; Adjust(); }
SetFullLocation(int loc)78   inline void SetFullLocation(int loc) { m_position = loc & 0xFFFFFF; m_mem_space = (loc >> 24); Adjust(); }
Set(const cHeadCPU & in_head)79   inline void Set(const cHeadCPU& in_head) { m_position = in_head.m_position; m_mem_space = in_head.m_mem_space; }
AbsSet(int new_pos)80   inline void AbsSet(int new_pos) { m_position = new_pos; }
81 
Jump(int jump)82   inline void Jump(int jump) { m_position += jump; Adjust(); }
AbsJump(int jump)83   inline void AbsJump(int jump) { m_position += jump; }
84   inline void LoopJump(int jump);
85 
Advance()86   inline void Advance() { m_position++; Adjust(); }
Retreat()87   inline void Retreat() { m_position--; Adjust(); }
88 
GetInst()89   inline const cInstruction& GetInst() const { return GetMemory()[m_position]; }
GetInst(int offset)90   inline const cInstruction& GetInst(int offset) const { return GetMemory()[m_position + offset]; }
91   inline cInstruction GetNextInst() const;
92 
SetInst(const cInstruction & value)93   inline void SetInst(const cInstruction& value) { GetMemory()[m_position] = value; }
InsertInst(const cInstruction & inst)94   inline void InsertInst(const cInstruction& inst) { GetMemory().Insert(m_position, inst); }
RemoveInst()95   inline void RemoveInst() { GetMemory().Remove(m_position); }
96 
SetFlagCopied()97   inline void SetFlagCopied() { return GetMemory().SetFlagCopied(m_position); }
SetFlagMutated()98   inline void SetFlagMutated() { return GetMemory().SetFlagMutated(m_position); }
SetFlagExecuted()99   inline void SetFlagExecuted() { return GetMemory().SetFlagExecuted(m_position); }
SetFlagBreakpoint()100   inline void SetFlagBreakpoint() { return GetMemory().SetFlagBreakpoint(m_position); }
SetFlagPointMut()101   inline void SetFlagPointMut() { return GetMemory().SetFlagPointMut(m_position); }
SetFlagCopyMut()102   inline void SetFlagCopyMut() { return GetMemory().SetFlagCopyMut(m_position); }
103 
ClearFlagCopied()104   inline void ClearFlagCopied() { return GetMemory().ClearFlagCopied(m_position); }
ClearFlagMutated()105   inline void ClearFlagMutated() { return GetMemory().ClearFlagMutated(m_position); }
ClearFlagExecuted()106   inline void ClearFlagExecuted() { return GetMemory().ClearFlagExecuted(m_position); }
ClearFlagBreakpoint()107   inline void ClearFlagBreakpoint() { return GetMemory().ClearFlagBreakpoint(m_position); }
ClearFlagPointMut()108   inline void ClearFlagPointMut() { return GetMemory().ClearFlagPointMut(m_position); }
ClearFlagCopyMut()109   inline void ClearFlagCopyMut() { return GetMemory().ClearFlagCopyMut(m_position); }
110 
111   // Operator Overloading...
112   inline cHeadCPU& operator=(const cHeadCPU& in_cpu_head);
113   inline cHeadCPU& operator++() { m_position++; Adjust(); return *this; }
114   inline cHeadCPU& operator--() { m_position--; Adjust(); return *this; }
115   inline cHeadCPU& operator++(int) { return operator++(); }
116   inline cHeadCPU& operator--(int) { return operator--(); }
117   inline int operator-(const cHeadCPU& in_cpu_head) { return m_position - in_cpu_head.m_position; }
118   inline bool operator==(const cHeadCPU& in_cpu_head) const;
119 
120   // Bool Tests...
AtFront()121   inline bool AtFront() const { return (m_position == 0); }
AtEnd()122   inline bool AtEnd() const { return (m_position + 1 == GetMemory().GetSize()); }
InMemory()123   inline bool InMemory() const { return (m_position >= 0 && m_position < GetMemory().GetSize()); }
124 };
125 
126 
cHeadCPU(cHardwareBase * hw,int pos,int ms)127 inline cHeadCPU::cHeadCPU(cHardwareBase* hw, int pos, int ms)
128   : m_hardware(hw), m_position(pos), m_mem_space(ms), m_cached_ms(-1)
129 {
130   if (hw) {
131     if (pos || ms) Adjust();
132     else {
133       m_cached_ms = 0;
134       m_memory = &m_hardware->GetMemory(0);
135     }
136   }
137 }
138 
cHeadCPU(const cHeadCPU & in_cpu_head)139 inline cHeadCPU::cHeadCPU(const cHeadCPU& in_cpu_head)
140 {
141   m_hardware = in_cpu_head.m_hardware;
142   m_position = in_cpu_head.m_position;
143   m_mem_space = in_cpu_head.m_mem_space;
144   m_cached_ms = in_cpu_head.m_cached_ms;
145   m_memory = in_cpu_head.m_memory;
146 }
147 
LoopJump(int jump)148 inline void cHeadCPU::LoopJump(int jump)
149 {
150   m_position += jump;
151 
152   // keep in range
153   m_position %= GetMemory().GetSize();
154   if (m_position <= 0) m_position += GetMemory().GetSize();
155 }
156 
157 inline cHeadCPU& cHeadCPU::operator=(const cHeadCPU& in_cpu_head)
158 {
159   m_hardware = in_cpu_head.m_hardware;
160   m_position = in_cpu_head.m_position;
161   m_mem_space = in_cpu_head.m_mem_space;
162   return *this;
163 }
164 
165 inline bool cHeadCPU::operator==(const cHeadCPU& in_cpu_head) const
166 {
167   return (m_hardware == in_cpu_head.m_hardware) && (m_position == in_cpu_head.m_position) &&
168   (m_mem_space == in_cpu_head.m_mem_space);
169 }
170 
GetNextInst()171 inline cInstruction cHeadCPU::GetNextInst() const
172 {
173   return (AtEnd()) ? m_hardware->GetInstSet().GetInstError() : GetMemory()[m_position + 1];
174 }
175 
176 #endif
177