diff options
author | Tom Stellard <tstellar@gmail.com> | 2010-12-29 02:19:05 -0800 |
---|---|---|
committer | Tom Stellard <tstellar@gmail.com> | 2010-12-29 02:19:05 -0800 |
commit | e70c6bfb0970de17d02528b44df6e11c159d552c (patch) | |
tree | 534a7b1092679f8ad0cef40d40cc71dd088643f2 | |
parent | ff43be28b9a0303b367247bbfc15a3fa4b1d228b (diff) |
Add abs_instruction
-rw-r--r-- | emulator.cpp | 7 | ||||
-rw-r--r-- | evaluator.cpp | 36 | ||||
-rw-r--r-- | evaluator.h | 8 | ||||
-rw-r--r-- | instruction.cpp | 23 | ||||
-rw-r--r-- | instruction.h | 7 | ||||
-rw-r--r-- | program.cpp | 10 | ||||
-rw-r--r-- | program.h | 3 | ||||
-rw-r--r-- | register_address.cpp | 1 | ||||
-rw-r--r-- | register_address.h | 3 |
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++); +} @@ -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 { |