-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathposndir.c
265 lines (237 loc) · 9.04 KB
/
posndir.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: ALIGN, EVEN, ORG directives
*
****************************************************************************/
#include "globals.h"
#include "parser.h"
#include "segment.h"
#include "expreval.h"
#include "types.h"
#include "listing.h"
#include "posndir.h"
#include "fastpass.h"
#include "fixup.h"
#include "input.h"
#include "myassert.h"
static const uint_8 NopList16[] = {
3, /* objlen of first NOP pattern */
0x2E, 0x8b, 0xc0, /* MOV AX,AX */
/* v2.11: Masm v6+ uses 8B CO; Masm v5 uses 87 DB (xchg bx, bx) */
//0x89, 0xc0, /* MOV AX,AX */
0x8b, 0xc0, /* MOV AX,AX */
0x90 /* NOP */
};
/* 32bit alignment fillers.
For 5 bytes, Masm uses "add eax,dword ptr 0",
which modifies the flags!
*/
static const uint_8 NopList32[] = {
7,
0x8d,0xa4,0x24,0,0,0,0, /* lea esp,[esp+00000000] */
0x8d,0x80,0,0,0,0, /* lea eax,[eax+00000000] */
#if 0
0x8d,0x40,0x00, /* lea eax,[eax+00] */
0x8b,0xc9, /* mov ecx,ecx */
#else
0x2e,0x8d,0x44,0x20,0x00, /* lea eax,cs:[eax+no_index_reg+00H] */
#endif
0x8d,0x44,0x20,0x00, /* lea eax,[eax+no_index_reg+00H] */
0x8d,0x40,0x00, /* lea eax,[eax+00H] */
0x8b,0xff, /* mov edi,edi */
0x90 /* nop */
};
#if AMD64_SUPPORT
static const uint_8 NopList64[] = {
7,
0x0f,0x1f,0x80,0,0,0,0, /* nop dword ptr [rax+0] */
0x66,0x0f,0x1f,0x44,0,0, /* nop word ptr [rax+rax] */
0x0f,0x1f,0x44,0,0, /* nop dword ptr [rax+rax] */
0x0f,0x1f,0x40,0, /* nop dword ptr [rax] */
0x0f,0x1f,0, /* nop dword ptr [rax] */
0x66,0x90, /* xchg ax,ax */
0x90, /* nop */
};
/* just use the 32bit nops for 64bit */
static const uint_8 * const NopLists[] = { NopList16, NopList32, NopList64 };
#else
static const uint_8 * const NopLists[] = { NopList16, NopList32 };
#endif
ret_code OrgDirective( int i, struct asm_tok tokenarray[] )
/*********************************************************/
{
//struct asym *sym;
//int_32 value = 0;
struct expr opndx;
DebugMsg1(("OrgDirective(%u) enter\n", i));
i++;
/* v2.09: if -Zne is set, don't allow forward reference in ORG argument */
//if ( ( ERROR == EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) ) )
if ( ( ERROR == EvalOperand( &i, tokenarray, Token_Count, &opndx, Options.strict_masm_compat ? EXPF_NOUNDEF : 0 ) ) )
return( ERROR );
if ( tokenarray[i].token != T_FINAL ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
if ( CurrStruct ) {
if ( opndx.kind == EXPR_CONST )
return( SetStructCurrentOffset( opndx.value ) );
} else {
if( CurrSeg == NULL ) {
return( EmitError( MUST_BE_IN_SEGMENT_BLOCK ) );
}
#if FASTPASS
if ( StoreState == FALSE ) FStoreLine(0);
#endif
/* v2.04: added */
if ( Parse_Pass == PASS_1 && CurrSeg->e.seginfo->FixupList.head )
CurrSeg->e.seginfo->FixupList.head->orgoccured = TRUE;
if ( opndx.kind == EXPR_CONST )
return( SetCurrOffset( CurrSeg, opndx.value, FALSE, FALSE ) );
else if ( opndx.kind == EXPR_ADDR && opndx.indirect == FALSE )
return( SetCurrOffset( CurrSeg, opndx.sym->offset + opndx.value, FALSE, FALSE ) );
}
return( EmitError( ORG_NEEDS_A_CONSTANT_OR_LOCAL_OFFSET ) );
}
static void fill_in_objfile_space( unsigned size )
/************************************************/
{
int i;
int nop_type;
/* emit
- nothing ... for BSS
- x'00' ... for DATA
- nops ... for CODE
*/
/* v2.04: no output if nothing has been written yet */
if( CurrSeg->e.seginfo->written == FALSE ) {
SetCurrOffset( CurrSeg, size, TRUE, TRUE );
} else if( CurrSeg->e.seginfo->segtype != SEGTYPE_CODE ) {
FillDataBytes( 0x00, size ); /* just output nulls */
} else {
/* output appropriate NOP type instructions to fill in the gap */
while( size > NopLists[ ModuleInfo.Ofssize ][0] ) {
for( i = 1; i <= NopLists[ ModuleInfo.Ofssize ][0]; i++ ) {
OutputByte( NopLists[ ModuleInfo.Ofssize ][i] );
}
size -= NopLists[ ModuleInfo.Ofssize ][0];
}
if( size == 0 ) return;
i=1; /* here i is the index into the NOP table */
for( nop_type = NopLists[ ModuleInfo.Ofssize ][0]; nop_type > size ; nop_type-- ) {
i+=nop_type;
}
/* i now is the index of the 1st part of the NOP that we want */
for( ; nop_type > 0; nop_type--,i++ ) {
OutputByte( NopLists[ ModuleInfo.Ofssize ][i] );
}
}
}
/* align current offset to value ( alignment is 2^value ) */
void AlignCurrOffset( int value )
/*******************************/
{
int seg_align;
int alignment = (1 << value);
unsigned int CurrAddr;
CurrAddr = GetCurrOffset();
seg_align = CurrAddr % alignment;
if( seg_align ) {
alignment -= seg_align;
fill_in_objfile_space( alignment );
}
}
#define align_value opndx.value
ret_code AlignDirective( int i, struct asm_tok tokenarray[] )
/***********************************************************/
{
int seg_align;
struct expr opndx;
uint_32 CurrAddr;
char buffer[32];
DebugMsg1(("AlignDirective enter\n"));
switch( tokenarray[i].tokval ) {
case T_ALIGN:
i++;
if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR )
return( ERROR );
if ( opndx.kind == EXPR_CONST ) {
int_32 power;
/* check that the parm is a power of 2 */
for( power = 1; power < align_value; power <<= 1 );
if( power != align_value ) {
return( EmitErr( POWER_OF_2, align_value ) );
}
} else if ( opndx.kind == EXPR_EMPTY ) { /* ALIGN without argument? */
/* v2.03: special STRUCT handling was missing */
if ( CurrStruct )
align_value = CurrStruct->e.structinfo->alignment;
else
align_value = GetCurrSegAlign();
} else {
return( EmitError( CONSTANT_EXPECTED ) );
}
break;
case T_EVEN:
align_value = 2;
i++;
break;
}
if ( tokenarray[i].token != T_FINAL ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
}
/* ALIGN/EVEN inside a STRUCT definition? */
if ( CurrStruct )
return( AlignInStruct( align_value ));
#if FASTPASS
if ( StoreState == FALSE ) FStoreLine(0);
#endif
seg_align = GetCurrSegAlign(); /* # of bytes */
if( seg_align <= 0 ) {
return( EmitError( MUST_BE_IN_SEGMENT_BLOCK ) );
}
if( align_value > seg_align ) {
if ( Parse_Pass == PASS_1 )
EmitWarn( 1, ALIGN_TOO_HIGH, myltoa( align_value, buffer, 10, FALSE, FALSE ) );
//return( ERROR ); /* v2.0: don't exit */
}
/* v2.04: added, Skip backpatching after ALIGN occured */
if ( Parse_Pass == PASS_1 && CurrSeg && CurrSeg->e.seginfo->FixupList.head )
CurrSeg->e.seginfo->FixupList.head->orgoccured = TRUE;
/* find out how many bytes past alignment we are & add the remainder */
/* store temp. value */
CurrAddr = GetCurrOffset();
seg_align = CurrAddr % align_value;
if( seg_align ) {
align_value -= seg_align;
fill_in_objfile_space( align_value );
}
if ( CurrFile[LST] ) {
LstWrite( LSTTYPE_DATA, CurrAddr, NULL );
}
DebugMsg1(("AlignDirective exit\n"));
return( NOT_ERROR );
}