summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--emulator.cpp7
-rw-r--r--evaluator.cpp36
-rw-r--r--evaluator.h8
-rw-r--r--instruction.cpp23
-rw-r--r--instruction.h7
-rw-r--r--program.cpp10
-rw-r--r--program.h3
-rw-r--r--register_address.cpp1
-rw-r--r--register_address.h3
9 files changed, 88 insertions, 10 deletions
diff --git a/emulator.cpp b/emulator.cpp
index c793ddf..14377ac 100644
--- a/emulator.cpp
+++ b/emulator.cpp
@@ -31,6 +31,7 @@ emulator::run()
return false;
}
m_immediate_regs = p->m_immediate_regs;
+ m_private_regs = std::vector<value *>(p->num_private_regs);
std::vector<instruction *>::iterator it;
for(it = p->m_instructions.begin();
it < p->m_instructions.end(); ++it) {
@@ -82,6 +83,7 @@ emulator::get_value(register_address addr)
case REGISTER_TYPE_OUT: return m_out_regs[index]->clone();
case REGISTER_TYPE_IMMEDIATE: return m_immediate_regs[index]->clone();
case REGISTER_TYPE_IN: return m_input_regs[index]->clone();
+ case REGISTER_TYPE_PRIVATE: return m_private_regs[index]->clone();
default:
std::cerr << __FUNCTION__ << " unknown register type: "
<< addr.m_type << "\n";
@@ -105,6 +107,11 @@ emulator::set_value(
delete m_out_regs[index];
m_out_regs[index] = val;
break;
+ case REGISTER_TYPE_PRIVATE:
+ /*In theory, these registers should only be written once. */
+ delete m_private_regs[index];
+ m_private_regs[index] = val;
+ break;
default:
assert(0);
}
diff --git a/evaluator.cpp b/evaluator.cpp
index 0d50b98..c182bcd 100644
--- a/evaluator.cpp
+++ b/evaluator.cpp
@@ -1,3 +1,5 @@
+#include <math.h>
+
#include "evaluator.h"
#include "value.h"
@@ -13,11 +15,8 @@ evaluator::evaluate(
value * l,
value * r)
{
- if (!l || !r) {
- return default_evaluate(l, r);
- }
- enum value_type l_type = l->get_type();
- enum value_type r_type = r->get_type();
+ enum value_type l_type = get_value_type(l);
+ enum value_type r_type = get_value_type(r);
switch(l_type) {
case VALUE_TYPE_FLOAT:
return evaluate((float_value*)l, r);
@@ -36,7 +35,7 @@ evaluator::evaluate(
float_value * l,
value * r)
{
- enum value_type r_type = r->get_type();
+ enum value_type r_type = get_value_type(r);
switch(r_type) {
case VALUE_TYPE_FLOAT:
return evaluate(l, (float_value*)r);
@@ -50,7 +49,7 @@ evaluator::evaluate(
value * l,
float_value * r)
{
- enum value_type l_type = l->get_type();
+ enum value_type l_type = get_value_type(l);
switch(l_type) {
case VALUE_TYPE_FLOAT:
return evaluate((float_value*)l, r);
@@ -67,6 +66,12 @@ evaluator::default_evaluate(
return new tree_value(this, l, r);
}
+value_type
+evaluator::get_value_type(value * val)
+{
+ return val ? val->get_type() : VALUE_TYPE_FLOAT;
+}
+
std::string
evaluator::to_string()
{
@@ -83,7 +88,7 @@ add_evaluator::evaluate(
float_value * r)
{
float_value * new_val;
- if (!l->m_has_value || !r->m_has_value) {
+ if (!l || !r || !l->m_has_value || !r->m_has_value) {
return default_evaluate(l, r);
}
@@ -109,3 +114,18 @@ mul_evaluator::evaluate(
new_val = new float_value(l->m_value * r->m_value);
return new_val;
}
+
+abs_evaluator::abs_evaluator() :
+ evaluator("abs()")
+ { }
+
+value *
+abs_evaluator::evaluate(
+ float_value * l,
+ float_value * r)
+{
+ if (!l || !l->m_has_value) {
+ return default_evaluate(l, r);
+ }
+ return new float_value(fabsf(l->m_value));
+}
diff --git a/evaluator.h b/evaluator.h
index 2dd0c70..02c7ff6 100644
--- a/evaluator.h
+++ b/evaluator.h
@@ -28,6 +28,7 @@ protected:
value * l,
value * r);
private:
+ value_type get_value_type(value * val);
const char * m_display_name;
};
@@ -48,4 +49,11 @@ public:
float_value * r);
};
+class abs_evaluator : public evaluator {
+public:
+ abs_evaluator();
+ value * evaluate(
+ float_value * l,
+ float_value * r);
+};
#endif //EVALUATOR_H_
diff --git a/instruction.cpp b/instruction.cpp
index f02e0b8..1f6f81d 100644
--- a/instruction.cpp
+++ b/instruction.cpp
@@ -15,6 +15,25 @@ instruction::instruction(
m_src_reg_count(src_reg_count)
{ }
+void instruction::execute(emulator & emulator)
+{
+ unsigned int i;
+ for (i = 0; i < m_dst.size(); i++) {
+ value * l = NULL;
+ value * r = NULL;
+ switch(m_src_regs.size()) {
+ case 2:
+ r = emulator.get_value(m_src_regs[1][i]);
+ /* Fall trough */
+ case 1:
+ l = emulator.get_value(m_src_regs[0][i]);
+ break;
+ }
+ emulator.set_value(m_dst[i],
+ new tree_value(m_evaluator, l, r));
+ }
+}
+
void instruction::add_src_reg(std::vector<register_address> src_reg)
{
assert(m_src_regs.size() < m_src_reg_count);
@@ -96,3 +115,7 @@ mad_instruction::execute(emulator & emulator)
emulator.set_value(m_dst[i], mad);
}
}
+
+abs_instruction::abs_instruction(std::vector<register_address> dst) :
+ instruction("ABS", new abs_evaluator(), dst, 1)
+ { }
diff --git a/instruction.h b/instruction.h
index 1924e89..d178644 100644
--- a/instruction.h
+++ b/instruction.h
@@ -17,7 +17,7 @@ public:
evaluator * evaluator,
std::vector<register_address> dst,
unsigned int src_reg_count);
- virtual void execute(emulator & emulator) = 0;
+ virtual void execute(emulator & emulator);
virtual void add_src_reg(std::vector<register_address> src_reg);
protected:
@@ -63,4 +63,9 @@ public:
void execute(emulator & emulator);
};
+class abs_instruction : public instruction {
+public:
+ abs_instruction(std::vector<register_address> dst);
+};
+
#endif //INSTRUCTION_H_
diff --git a/program.cpp b/program.cpp
index 153246c..1d7f31b 100644
--- a/program.cpp
+++ b/program.cpp
@@ -2,6 +2,10 @@
#include "value.h"
+program::program() :
+ num_private_regs(0)
+ { }
+
register_address
program::add_immediate(float value)
{
@@ -14,3 +18,9 @@ program::add_instruction(instruction * inst)
{
m_instructions.push_back(inst);
}
+
+register_address
+program::alloc_private_reg()
+{
+ return register_address(REGISTER_TYPE_PRIVATE, num_private_regs++);
+}
diff --git a/program.h b/program.h
index fbee082..64c059a 100644
--- a/program.h
+++ b/program.h
@@ -10,11 +10,14 @@ class instruction;
class program {
public:
+ program();
register_address add_immediate(float value);
void add_instruction(instruction * inst);
+ register_address alloc_private_reg();
std::vector<instruction *> m_instructions;
std::vector<float_value *> m_immediate_regs;
+ unsigned int num_private_regs;
};
#endif //PROGRAM_H_
diff --git a/register_address.cpp b/register_address.cpp
index a942b91..afdb149 100644
--- a/register_address.cpp
+++ b/register_address.cpp
@@ -55,6 +55,7 @@ register_address::register_type_to_string(enum register_type type)
case REGISTER_TYPE_IN: return "IN";
case REGISTER_TYPE_OUT: return "OUT";
case REGISTER_TYPE_IMMEDIATE: return "IMM";
+ case REGISTER_TYPE_PRIVATE: return "PRIV";
default: return "NONE";
}
}
diff --git a/register_address.h b/register_address.h
index 7f1d1ae..524d134 100644
--- a/register_address.h
+++ b/register_address.h
@@ -9,7 +9,8 @@ enum register_type {
REGISTER_TYPE_CONST,
REGISTER_TYPE_IN,
REGISTER_TYPE_OUT,
- REGISTER_TYPE_IMMEDIATE
+ REGISTER_TYPE_IMMEDIATE,
+ REGISTER_TYPE_PRIVATE
};
enum swizzle {