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 */
99 Flags |= TypeOf (Expr->Type);
100 if (ED_NeedsTest (Expr)) {
104 switch (ED_GetLoc (Expr)) {
107 /* Absolute: numeric address or const */
108 g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
112 /* Global variable */
113 g_getstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal);
118 /* Static variable or literal in the literal pool */
119 g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
123 /* Register variable */
124 g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
128 /* Value on the stack */
129 g_getlocal (Flags, Expr->IVal);
133 /* The primary register - just test if necessary */
134 if (Flags & CF_TEST) {
140 /* Reference to address in primary with offset in Expr */
141 g_getind (Flags, Expr->IVal);
145 Internal ("Invalid location in LoadExpr: 0x%04X", ED_GetLoc (Expr));
148 /* Handle bit fields. The actual type may have been casted or
149 * converted, so be sure to always use unsigned ints for the
152 if (ED_IsBitField (Expr)) {
153 unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST);
154 /* Shift right by the bit offset */
155 g_asr (F, Expr->BitOffs);
156 /* And by the width */
157 g_and (F, (0x0001U << Expr->BitWidth) - 1U);
160 /* Expression was tested */
165 if (ED_IsLocExpr (Expr)) {
166 if (Expr->IVal != 0) {
167 /* We have an expression in the primary plus a constant
168 * offset. Adjust the value in the primary accordingly.
170 Flags |= TypeOf (Expr->Type);
171 g_inc (Flags | CF_CONST, Expr->IVal);
174 /* Constant of some sort, load it into the primary */
175 LoadConstant (Flags, Expr);
178 /* Are we testing this value? */
179 if (ED_NeedsTest (Expr)) {
180 /* Yes, force a test */
181 Flags |= TypeOf (Expr->Type);