1 
2 /* "Species" - a CoreWars evolver.  Copyright (C) 2003 'Varfar'
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 1, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 /* this file implements a lookup for code that is interested in whether something is a branch or not */
20 
21 #include "opcode_branch_lookup.hpp"
22 #include "error.hpp"
23 
24 #include "species.hpp"
25 
26 namespace { // anon
27 
28 	const struct {
29 		unsigned num;
30  		MODIFIER lookup[MODIFIER_LAST];
31 	} EFFECTIVE_MODIFIER_LOOKUP[OPCODE_LAST] = {
32 		{1, { mF, mF, mF,mF, mF,  mF, mF}},	// * DAT				/* must be 0 */
33 		{1, { mF, mF, mF,mF, mF,  mF, mF}},	// * SPL,
34 		{7, { mF, mA, mB,mAB,mBA, mX, mI}},	// * MOV,
35 		{3, { mF, mA, mB,mB, mA,  mF, mF}},	// * DJN,
36 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * ADD,
37 		{3, { mF, mA, mB,mB, mA,  mF, mF}},	// * JMZ,
38 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * SUB,
39 		{7, { mF, mA, mB,mAB,mBA, mX, mI}},	// * SEQ,
40 		{7, { mF, mA, mB,mAB,mBA, mX, mI}},	// * SNE,
41 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * SLT,
42 		{5, { mF, mA, mB,mB, mA,  mF, mF}},	// * JMN,
43 		{1, { mF, mF, mF,mF, mF,  mF, mF}},	// * JMP,
44 		{1, { mF, mF, mF,mF, mF,  mF, mF}},	// * NOP,
45 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * MUL,
46 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * MODM,
47 		{6, { mF, mA, mB,mAB,mBA, mX, mF}},	// * DIV,
48 		{7, { mF, mA, mB,mAB,mBA, mX, mI}},	// LDP,
49 		{7, { mF, mA, mB,mAB,mBA, mX, mI}}	// STP,				/* 18 */
50 	};
51 
52 } // anon
53 
54 const bool
55 	OPCODE_IS_BRANCH[OPCODE_LAST] = {
56 		false, // DAT,				/* must be 0 */
57 		true,  // SPL,
58 		false, // MOV,
59 		true,  // DJN,
60 		false, // ADD,
61 		true,  // JMZ,
62 		false, // SUB,
63 		false, // SEQ,
64 		false, // SNE,
65 		false, // SLT,
66 		true,  // JMN,
67 		true,  // JMP,
68 		false, // NOP,
69 		false, // MUL,
70 		false, // MODM,
71 		false, // DIV,
72 		false, // LDP,
73 		false  // STP,				/* 18 */
74 	},
75 	OPCODE_IS_SKIP[OPCODE_LAST] = {
76 		false, // DAT,				/* must be 0 */
77 		false, // SPL,
78 		false, // MOV,
79 		false, // DJN,
80 		false, // ADD,
81 		false, // JMZ,
82 		false, // SUB,
83 		true,  // SEQ,
84 		true,  // SNE,
85 		true,  // SLT,
86 		false, // JMN,
87 		false, // JMP,
88 		false, // NOP,
89 		false, // MUL,
90 		false, // MODM,
91 		false, // DIV,
92 		false, // LDP,
93 		false  // STP,				/* 18 */
94 	},
95 	OPCODE_CONTINUES[OPCODE_LAST] = {
96 		false, // DAT,				/* must be 0 */
97 		true,  // SPL,
98 		true,  // MOV,
99 		true,  // DJN,
100 		true,  // ADD,
101 		true,  // JMZ,
102 		true,  // SUB,
103 		true,  // SEQ,
104 		true,  // SNE,
105 		true,  // SLT,
106 		true,  // JMN,
107 		false, // JMP,
108 		true,  // NOP,
109 		true,  // MUL,
110 		true,  // MODM,
111 		true,  // DIV,
112 		true,  // LDP,
113 		true  // STP,				/* 18 */
114 	},
115 	OPCODE_IS_BRANCH_OR_SKIP[OPCODE_LAST] = {
116 		false, // DAT,				/* must be 0 */
117 		true,  // SPL,
118 		false, // MOV,
119 		true,  // DJN,
120 		false, // ADD,
121 		true,  // JMZ,
122 		false, // SUB,
123 		true,  // SEQ,
124 		true,  // SNE,
125 		true,  // SLT,
126 		true,  // JMN,
127 		true,  // JMP,
128 		false, // NOP,
129 		false, // MUL,
130 		false, // MODM,
131 		false, // DIV,
132 		false, // LDP,
133 		false  // STP,				/* 18 */
134 	};
135 
136 const int
137 	NUM_OPCODE_BRANCHES = 5,
138 	NUM_OPCODE_SKIPS = 3,
139 	NUM_OPCODE_CONTINUES = 16;
140 
141 static const char
142 	*S_MNEMONIC_OPCODE[OPCODE_LAST] = {
143 		"DAT","SPL","MOV","DJN","ADD","JMZ","SUB","SEQ","SNE","SLT","JMN","JMP","NOP","MUL","MOD","DIV","LDP","STP" },
144 	*S_MNEMONIC_MODIFIER[MODIFIER_LAST] = {
145 		"F","A","B","AB","BA","X","I"},
146 	S_MNEMONIC_ADDRMODE[ADDRMODE_LAST] = {
147 		'$','#','@','<','>','*','{','}'};
148 
MNEMONIC_OPCODE(const OPCODE opcode)149 const char *MNEMONIC_OPCODE(const OPCODE opcode) {
150 	if(safety_checks) {
151 		if((opcode < 0) || (opcode > OPCODE_LAST))
152 			PANIC(MISC,"opcode out of range",NULL);
153 	}
154 	return S_MNEMONIC_OPCODE[opcode];
155 }
156 
MNEMONIC_MODIFIER(const MODIFIER modifier)157 const char *MNEMONIC_MODIFIER(const MODIFIER modifier) {
158 	if(safety_checks) {
159 		if((modifier < 0) || (modifier >MODIFIER_LAST))
160 			PANIC(MISC,"modifier out of range",NULL);
161 	}
162 	return S_MNEMONIC_MODIFIER[modifier];
163 }
164 
MNEMONIC_ADDRMODE(const ADDRMODE addrmode)165 const char MNEMONIC_ADDRMODE(const ADDRMODE addrmode) {
166 	if(safety_checks) {
167 		if((addrmode < 0) || (addrmode > ADDRMODE_LAST))
168 			PANIC(MISC,"addrmode out of range",NULL);
169 	}
170 	return S_MNEMONIC_ADDRMODE[addrmode];
171 }
172 
EFFECTIVE_MODIFIER(const OPCODE opcode,const MODIFIER modifier)173 MODIFIER EFFECTIVE_MODIFIER(const OPCODE opcode,const MODIFIER modifier) {
174 	MODIFIER ret = modifier;
175 	if(safety_checks) {
176 		if(opcode > OPCODE_LAST)
177 			PANIC(MISC,"opcode out of range",NULL);
178 		if(modifier > MODIFIER_LAST)
179 			PANIC(MISC,"modifier out of range",NULL);
180 	}
181 	return EFFECTIVE_MODIFIER_LOOKUP[opcode].lookup[modifier];
182 	return ret;
183 }
184 
EFFECTIVE_MODIFIERS(const OPCODE opcode)185 unsigned EFFECTIVE_MODIFIERS(const OPCODE opcode) {
186 	return EFFECTIVE_MODIFIER_LOOKUP[opcode].num;
187 }
188