1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 1996-2017 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | /* |
35 | * exprlib.c |
36 | * |
37 | * Library routines to manipulate expression data types. |
38 | */ |
39 | |
40 | #include "nasm.h" |
41 | |
42 | /* |
43 | * Return true if the argument is a simple scalar. (Or a far- |
44 | * absolute, which counts.) |
45 | */ |
46 | bool is_simple(const expr *vect) |
47 | { |
48 | while (vect->type && !vect->value) |
49 | vect++; |
50 | if (!vect->type) |
51 | return true; |
52 | if (vect->type != EXPR_SIMPLE) |
53 | return false; |
54 | do { |
55 | vect++; |
56 | } while (vect->type && !vect->value); |
57 | if (vect->type && vect->type < EXPR_SEGBASE + SEG_ABS) |
58 | return false; |
59 | return true; |
60 | } |
61 | |
62 | /* |
63 | * Return true if the argument is a simple scalar, _NOT_ a far- |
64 | * absolute. |
65 | */ |
66 | bool is_really_simple(const expr *vect) |
67 | { |
68 | while (vect->type && !vect->value) |
69 | vect++; |
70 | if (!vect->type) |
71 | return true; |
72 | if (vect->type != EXPR_SIMPLE) |
73 | return false; |
74 | do { |
75 | vect++; |
76 | } while (vect->type && !vect->value); |
77 | if (vect->type) |
78 | return false; |
79 | return true; |
80 | } |
81 | |
82 | /* |
83 | * Return true if the argument is relocatable (i.e. a simple |
84 | * scalar, plus at most one segment-base, possibly a subtraction |
85 | * of the current segment base, plus possibly a WRT). |
86 | */ |
87 | bool is_reloc(const expr *vect) |
88 | { |
89 | bool has_rel = false; /* Has a self-segment-subtract */ |
90 | bool has_seg = false; /* Has a segment base */ |
91 | |
92 | for (; vect->type; vect++) { |
93 | if (!vect->value) { |
94 | /* skip value-0 terms */ |
95 | continue; |
96 | } else if (vect->type < EXPR_SIMPLE) { |
97 | /* false if a register is present */ |
98 | return false; |
99 | } else if (vect->type == EXPR_SIMPLE) { |
100 | /* skip over a pure number term... */ |
101 | continue; |
102 | } else if (vect->type == EXPR_WRT) { |
103 | /* skip over a WRT term... */ |
104 | continue; |
105 | } else if (vect->type < EXPR_SEGBASE) { |
106 | /* other special type -> problem */ |
107 | return false; |
108 | } else if (vect->value == 1) { |
109 | if (has_seg) |
110 | return false; /* only one segbase allowed */ |
111 | has_seg = true; |
112 | } else if (vect->value == -1) { |
113 | if (vect->type != location.segment + EXPR_SEGBASE) |
114 | return false; /* can only subtract current segment */ |
115 | if (has_rel) |
116 | return false; /* already is relative */ |
117 | has_rel = true; |
118 | } |
119 | } |
120 | |
121 | return true; |
122 | } |
123 | |
124 | /* |
125 | * Return true if the argument contains an `unknown' part. |
126 | */ |
127 | bool is_unknown(const expr *vect) |
128 | { |
129 | while (vect->type && vect->type < EXPR_UNKNOWN) |
130 | vect++; |
131 | return (vect->type == EXPR_UNKNOWN); |
132 | } |
133 | |
134 | /* |
135 | * Return true if the argument contains nothing but an `unknown' |
136 | * part. |
137 | */ |
138 | bool is_just_unknown(const expr *vect) |
139 | { |
140 | while (vect->type && !vect->value) |
141 | vect++; |
142 | return (vect->type == EXPR_UNKNOWN); |
143 | } |
144 | |
145 | /* |
146 | * Return the scalar part of a relocatable vector. (Including |
147 | * simple scalar vectors - those qualify as relocatable.) |
148 | */ |
149 | int64_t reloc_value(const expr *vect) |
150 | { |
151 | while (vect->type && !vect->value) |
152 | vect++; |
153 | if (!vect->type) |
154 | return 0; |
155 | if (vect->type == EXPR_SIMPLE) |
156 | return vect->value; |
157 | else |
158 | return 0; |
159 | } |
160 | |
161 | /* |
162 | * Return the segment number of a relocatable vector, or NO_SEG for |
163 | * simple scalars. |
164 | */ |
165 | int32_t reloc_seg(const expr *vect) |
166 | { |
167 | for (; vect->type; vect++) { |
168 | if (vect->type >= EXPR_SEGBASE && vect->value == 1) |
169 | return vect->type - EXPR_SEGBASE; |
170 | } |
171 | |
172 | return NO_SEG; |
173 | } |
174 | |
175 | /* |
176 | * Return the WRT segment number of a relocatable vector, or NO_SEG |
177 | * if no WRT part is present. |
178 | */ |
179 | int32_t reloc_wrt(const expr *vect) |
180 | { |
181 | while (vect->type && vect->type < EXPR_WRT) |
182 | vect++; |
183 | if (vect->type == EXPR_WRT) { |
184 | return vect->value; |
185 | } else |
186 | return NO_SEG; |
187 | } |
188 | |
189 | /* |
190 | * Return true if this expression contains a subtraction of the location |
191 | */ |
192 | bool is_self_relative(const expr *vect) |
193 | { |
194 | for (; vect->type; vect++) { |
195 | if (vect->type == location.segment + EXPR_SEGBASE && vect->value == -1) |
196 | return true; |
197 | } |
198 | |
199 | return false; |
200 | } |
201 | |