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) 2000 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 "ModExpr.h"
22 #include "Bytecode.h"
23 #include "RCX_Cmd.h"
24
25 #define NON_VOLATILE_MASK (TYPEMASK(kRCX_VariableType) + \
26 TYPEMASK(kRCX_ConstantType))
27
28
Clone(Mapping * b) const29 Expr* ModExpr::Clone(Mapping *b) const
30 {
31 return new ModExpr(Get(0)->Clone(b), Get(1)->Clone(b));
32 }
33
34
Evaluate(int & value) const35 bool ModExpr::Evaluate(int &value) const
36 {
37 int v1, v2;
38
39 if (!Get(0)->Evaluate(v1)) return false;
40 if (!Get(1)->Evaluate(v2)) return false;
41
42 value = v1 % v2;
43
44 return true;
45 }
46
47
EmitAny_(Bytecode & b) const48 RCX_Value ModExpr::EmitAny_(Bytecode &b) const
49 {
50 int dst;
51
52 dst = GetTempVar(b);
53 if (dst < 0)
54 return kIllegalEA;
55
56 RCX_Value ea = RCX_VALUE(kRCX_VariableType, dst);
57
58 if (EmitCalculation(b, dst))
59 {
60 return ea;
61 }
62 else
63 {
64 b.ReleaseTempEA(ea);
65 return kIllegalEA;
66 }
67 }
68
69
EmitTo_(Bytecode & b,int dst) const70 bool ModExpr::EmitTo_(Bytecode &b, int dst) const
71 {
72 if (Get(1)->Contains(dst) || Get(0)->Contains(dst))
73 {
74 RCX_Value ea;
75
76 ea = EmitAny_(b);
77 if (ea==kIllegalEA) return false;
78
79 b.AddMove(dst, ea);
80 b.ReleaseTempEA(ea);
81 return true;
82 }
83 else
84 {
85 return EmitCalculation(b, dst);
86 }
87 }
88
89
EmitCalculation(Bytecode & b,int dst) const90 bool ModExpr::EmitCalculation(Bytecode &b, int dst) const
91 {
92 RCX_Value m, n;
93 RCX_Cmd cmd;
94
95 m = Get(0)->EmitConstrained(b, NON_VOLATILE_MASK);
96 if (m == kIllegalEA) return false;
97
98 n = Get(1)->EmitConstrained(b, NON_VOLATILE_MASK);
99 if (n== kIllegalEA)
100 {
101 b.ReleaseTempEA(m);
102 return false;
103 }
104
105 // dst = m
106 b.AddMove(dst, m);
107
108 // dst /= n
109 cmd.MakeVar(kRCX_DivVar ,dst, n);
110 b.Add(cmd);
111
112 // dst *= n
113 cmd.MakeVar(kRCX_MulVar, dst, n);
114 b.Add(cmd);
115
116 // dst -= m
117 cmd.MakeVar(kRCX_SubVar, dst, m);
118 b.Add(cmd);
119
120 // dst *= -1
121 cmd.MakeVar(kRCX_MulVar, dst, RCX_VALUE(kRCX_ConstantType, -1));
122 b.Add(cmd);
123
124 b.ReleaseTempEA(m);
125 b.ReleaseTempEA(n);
126
127 return true ;
128 }
129
130