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