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