/* "Species" - a CoreWars evolver. Copyright (C) 2003 'Varfar' * * 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 1, 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., * 675 Mass Ave, Cambridge, MA 02139, USA. */ /* this file implements a lookup for code that is interested in whether something is a branch or not */ #include "opcode_branch_lookup.hpp" #include "error.hpp" #include "species.hpp" namespace { // anon const struct { unsigned num; MODIFIER lookup[MODIFIER_LAST]; } EFFECTIVE_MODIFIER_LOOKUP[OPCODE_LAST] = { {1, { mF, mF, mF,mF, mF, mF, mF}}, // * DAT /* must be 0 */ {1, { mF, mF, mF,mF, mF, mF, mF}}, // * SPL, {7, { mF, mA, mB,mAB,mBA, mX, mI}}, // * MOV, {3, { mF, mA, mB,mB, mA, mF, mF}}, // * DJN, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * ADD, {3, { mF, mA, mB,mB, mA, mF, mF}}, // * JMZ, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * SUB, {7, { mF, mA, mB,mAB,mBA, mX, mI}}, // * SEQ, {7, { mF, mA, mB,mAB,mBA, mX, mI}}, // * SNE, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * SLT, {5, { mF, mA, mB,mB, mA, mF, mF}}, // * JMN, {1, { mF, mF, mF,mF, mF, mF, mF}}, // * JMP, {1, { mF, mF, mF,mF, mF, mF, mF}}, // * NOP, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * MUL, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * MODM, {6, { mF, mA, mB,mAB,mBA, mX, mF}}, // * DIV, {7, { mF, mA, mB,mAB,mBA, mX, mI}}, // LDP, {7, { mF, mA, mB,mAB,mBA, mX, mI}} // STP, /* 18 */ }; } // anon const bool OPCODE_IS_BRANCH[OPCODE_LAST] = { false, // DAT, /* must be 0 */ true, // SPL, false, // MOV, true, // DJN, false, // ADD, true, // JMZ, false, // SUB, false, // SEQ, false, // SNE, false, // SLT, true, // JMN, true, // JMP, false, // NOP, false, // MUL, false, // MODM, false, // DIV, false, // LDP, false // STP, /* 18 */ }, OPCODE_IS_SKIP[OPCODE_LAST] = { false, // DAT, /* must be 0 */ false, // SPL, false, // MOV, false, // DJN, false, // ADD, false, // JMZ, false, // SUB, true, // SEQ, true, // SNE, true, // SLT, false, // JMN, false, // JMP, false, // NOP, false, // MUL, false, // MODM, false, // DIV, false, // LDP, false // STP, /* 18 */ }, OPCODE_CONTINUES[OPCODE_LAST] = { false, // DAT, /* must be 0 */ true, // SPL, true, // MOV, true, // DJN, true, // ADD, true, // JMZ, true, // SUB, true, // SEQ, true, // SNE, true, // SLT, true, // JMN, false, // JMP, true, // NOP, true, // MUL, true, // MODM, true, // DIV, true, // LDP, true // STP, /* 18 */ }, OPCODE_IS_BRANCH_OR_SKIP[OPCODE_LAST] = { false, // DAT, /* must be 0 */ true, // SPL, false, // MOV, true, // DJN, false, // ADD, true, // JMZ, false, // SUB, true, // SEQ, true, // SNE, true, // SLT, true, // JMN, true, // JMP, false, // NOP, false, // MUL, false, // MODM, false, // DIV, false, // LDP, false // STP, /* 18 */ }; const int NUM_OPCODE_BRANCHES = 5, NUM_OPCODE_SKIPS = 3, NUM_OPCODE_CONTINUES = 16; static const char *S_MNEMONIC_OPCODE[OPCODE_LAST] = { "DAT","SPL","MOV","DJN","ADD","JMZ","SUB","SEQ","SNE","SLT","JMN","JMP","NOP","MUL","MOD","DIV","LDP","STP" }, *S_MNEMONIC_MODIFIER[MODIFIER_LAST] = { "F","A","B","AB","BA","X","I"}, S_MNEMONIC_ADDRMODE[ADDRMODE_LAST] = { '$','#','@','<','>','*','{','}'}; const char *MNEMONIC_OPCODE(const OPCODE opcode) { if(safety_checks) { if((opcode < 0) || (opcode > OPCODE_LAST)) PANIC(MISC,"opcode out of range",NULL); } return S_MNEMONIC_OPCODE[opcode]; } const char *MNEMONIC_MODIFIER(const MODIFIER modifier) { if(safety_checks) { if((modifier < 0) || (modifier >MODIFIER_LAST)) PANIC(MISC,"modifier out of range",NULL); } return S_MNEMONIC_MODIFIER[modifier]; } const char MNEMONIC_ADDRMODE(const ADDRMODE addrmode) { if(safety_checks) { if((addrmode < 0) || (addrmode > ADDRMODE_LAST)) PANIC(MISC,"addrmode out of range",NULL); } return S_MNEMONIC_ADDRMODE[addrmode]; } MODIFIER EFFECTIVE_MODIFIER(const OPCODE opcode,const MODIFIER modifier) { MODIFIER ret = modifier; if(safety_checks) { if(opcode > OPCODE_LAST) PANIC(MISC,"opcode out of range",NULL); if(modifier > MODIFIER_LAST) PANIC(MISC,"modifier out of range",NULL); } return EFFECTIVE_MODIFIER_LOOKUP[opcode].lookup[modifier]; return ret; } unsigned EFFECTIVE_MODIFIERS(const OPCODE opcode) { return EFFECTIVE_MODIFIER_LOOKUP[opcode].num; }