1 /*
2  * The contents of this file are subject to the Mozilla Public License
3  * Version 1.0 (the "License"); you may not use this file except in
4  * compliance with the License. You may obtain a copy of the License at
5  * http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
9  * License for the specific language governing rights and limitations
10  * under the License.
11  *
12  * The Initial Developer of this code is David Baum.
13  * Portions created by David Baum are Copyright (C) 1999 David Baum.
14  * All Rights Reserved.
15  *
16  * Portions created by John Hansen are Copyright (C) 2005 John Hansen.
17  * All Rights Reserved.
18  *
19  */
20 
21 #include "BinaryExpr.h"
22 #include "parser.h"
23 #include "Bytecode.h"
24 #include "RCX_Cmd.h"
25 #include "Program.h"
26 
27 
28 static RCX_VarCode GetBinaryCode(int op);
29 
GetBinaryCode(int op)30 static RCX_VarCode GetBinaryCode(int op)
31 {
32         const RCX_Target *t = gProgram->GetTarget();
33 	switch(op)
34 	{
35 		case '+':
36 			return kRCX_AddVar;
37 		case '-':
38 			return kRCX_SubVar;
39 		case '*':
40 			return kRCX_MulVar;
41 		case '/':
42 			return kRCX_DivVar;
43 		case '&':
44 			return kRCX_AndVar;
45 		case '|':
46 			return kRCX_OrVar;
47 		case '%':
48 			if (t->fType == kRCX_SwanTarget)
49 				return kRCX_ModVar;
50 			else
51 				return kRCX_IllegalVar;
52 		case LEFT:
53 			if (t->fType == kRCX_SwanTarget)
54 				return kRCX_ShlVar;
55 			else
56 				return kRCX_IllegalVar;
57 		case RIGHT:
58 			if (t->fType == kRCX_SwanTarget)
59 				return kRCX_ShrVar;
60 			else
61 				return kRCX_IllegalVar;
62 		case '^':
63 			if (t->fType == kRCX_SwanTarget)
64 				return kRCX_XOrVar;
65 			else
66 				return kRCX_IllegalVar;
67 		default:
68 			return kRCX_IllegalVar;
69 	}
70 }
71 
72 
BinaryExpr(Expr * lhs,int op,Expr * rhs)73 BinaryExpr::BinaryExpr(Expr *lhs, int op, Expr *rhs)
74 	: NodeExpr(lhs, rhs), fOp(op)
75 {
76 }
77 
78 
79 
Clone(Mapping * b) const80 Expr* BinaryExpr::Clone(Mapping *b) const
81 {
82 	return new BinaryExpr(Get(0)->Clone(b), fOp, Get(1)->Clone(b));
83 }
84 
85 
Evaluate(int & value) const86 bool BinaryExpr::Evaluate(int &value) const
87 {
88 	int v1, v2;
89 
90 	if (!Get(0)->Evaluate(v1)) return false;
91 	if (!Get(1)->Evaluate(v2)) return false;
92 
93 	switch(fOp)
94 	{
95 		case '+':
96 			value = v1 + v2;
97 			break;
98 		case '-':
99 			value = v1 - v2;
100 			break;
101 		case '*':
102 			value = v1 * v2;
103 			break;
104 		case '/':
105 			value = v1 / v2;
106 			break;
107 		case '&':
108 			value = v1 & v2;
109 			break;
110 		case '|':
111 			value = v1 | v2;
112 			break;
113 		case '%':
114 			value = v1 % v2;
115 			break;
116 		case LEFT:
117 			value =	v1 << v2;
118 			break;
119 		case RIGHT:
120 			value = v1 >> v2;
121 			break;
122 		case '^':
123 			value = v1 ^ v2;
124 			break;
125 		default:
126 			return false;
127 
128 	}
129 	return true;
130 }
131 
132 
EmitAny_(Bytecode & b) const133 RCX_Value BinaryExpr::EmitAny_(Bytecode &b) const
134 {
135 	RCX_Cmd cmd;
136 	RCX_Value ea;
137 	RCX_Value dstEA;
138 	int dst;
139 	RCX_VarCode code;
140 
141 	ea = Get(0)->EmitAny(b);
142 	if (ea == kIllegalEA) return ea;
143 
144 	if (b.IsTempEA(ea))
145 		dst = RCX_VALUE_DATA(ea);
146 	else
147 	{
148 		dst = GetTempVar(b);
149 		if (dst < 0)
150 			return kIllegalEA;
151 
152 		b.AddMove(dst, ea);
153 	}
154 
155 	code = GetBinaryCode(fOp);
156 	dstEA = RCX_VALUE(kRCX_VariableType, dst);
157 	ea = Get(1)->EmitMath(b);
158 	if (ea == kIllegalEA)
159 	{
160 		b.ReleaseTempEA(dstEA);
161 		return ea;
162 	}
163 
164 	cmd.MakeVar(code, dst, ea);
165 	b.Add(cmd);
166 	b.ReleaseTempEA(ea);
167 
168 	return dstEA;
169 }
170 
171 
EmitTo_(Bytecode & b,int dst) const172 bool BinaryExpr::EmitTo_(Bytecode &b, int dst) const
173 {
174 	if (Get(1)->Contains(dst))
175 		return Expr::EmitTo_(b, dst);
176 	else
177 	{
178 		Get(0)->EmitTo(b, dst);
179 
180 		RCX_Cmd cmd;
181 		RCX_VarCode code = GetBinaryCode(fOp);
182 		RCX_Value ea = Get(1)->EmitMath(b);
183 		if (ea == kIllegalEA) return false;
184 
185 		cmd.MakeVar(code, dst, ea);
186 		b.Add(cmd);
187 		b.ReleaseTempEA(ea);
188 		return true;
189 	}
190 }
191 
NeedsConstant(int op)192 bool BinaryExpr::NeedsConstant(int op)
193 {
194 	return GetBinaryCode(op) == kRCX_IllegalVar;
195 }
196