1 /*****************************************************************************/
5 /* Load an expression into the primary register */
9 /* (C) 2004-2009, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
45 /*****************************************************************************/
47 /*****************************************************************************/
51 static void LoadConstant (unsigned Flags, ExprDesc* Expr)
52 /* Load the primary register with some constant value. */
54 switch (ED_GetLoc (Expr)) {
58 g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
62 /* Global symbol, load address */
63 g_getimmed ((Flags | CF_EXTERNAL) & ~CF_CONST, Expr->Name, Expr->IVal);
68 /* Static symbol or literal, load address */
69 g_getimmed ((Flags | CF_STATIC) & ~CF_CONST, Expr->Name, Expr->IVal);
73 /* Register variable. Taking the address is usually not
76 if (IS_Get (&AllowRegVarAddr) == 0) {
77 Error ("Cannot take the address of a register variable");
79 g_getimmed ((Flags | CF_REGVAR) & ~CF_CONST, Expr->Name, Expr->IVal);
87 Internal ("Unknown constant type: %04X", Expr->Flags);
93 void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
94 /* Load an expression into the primary register if it is not already there. */
96 if (ED_IsLVal (Expr)) {
98 /* Dereferenced lvalue. If this is a bit field its type is unsigned.
99 * But if the field is completely contained in the lower byte, we will
100 * throw away the high byte anyway and may therefore load just the
103 if (ED_IsBitField (Expr)) {
104 Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS)? CF_CHAR : CF_INT;
105 Flags |= CF_UNSIGNED;
107 Flags |= TypeOf (Expr->Type);
109 if (ED_NeedsTest (Expr)) {
113 switch (ED_GetLoc (Expr)) {
116 /* Absolute: numeric address or const */
117 g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
121 /* Global variable */
122 g_getstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal);
127 /* Static variable or literal in the literal pool */
128 g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
132 /* Register variable */
133 g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
137 /* Value on the stack */
138 g_getlocal (Flags, Expr->IVal);
142 /* The primary register - just test if necessary */
143 if (Flags & CF_TEST) {
149 /* Reference to address in primary with offset in Expr */
150 g_getind (Flags, Expr->IVal);
154 Internal ("Invalid location in LoadExpr: 0x%04X", ED_GetLoc (Expr));
157 /* Handle bit fields. The actual type may have been casted or
158 * converted, so be sure to always use unsigned ints for the
161 if (ED_IsBitField (Expr)) {
162 unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST);
163 /* Shift right by the bit offset */
164 g_asr (F, Expr->BitOffs);
165 /* And by the width if the field doesn't end on an int boundary */
166 if (Expr->BitOffs + Expr->BitWidth != CHAR_BITS &&
167 Expr->BitOffs + Expr->BitWidth != INT_BITS) {
168 g_and (F, (0x0001U << Expr->BitWidth) - 1U);
172 /* Expression was tested */
177 if (ED_IsLocExpr (Expr)) {
178 if (Expr->IVal != 0) {
179 /* We have an expression in the primary plus a constant
180 * offset. Adjust the value in the primary accordingly.
182 Flags |= TypeOf (Expr->Type);
183 g_inc (Flags | CF_CONST, Expr->IVal);
186 /* Constant of some sort, load it into the primary */
187 LoadConstant (Flags, Expr);
190 /* Are we testing this value? */
191 if (ED_NeedsTest (Expr)) {
192 /* Yes, force a test */
193 Flags |= TypeOf (Expr->Type);