-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathm2omf.def
More file actions
288 lines (242 loc) · 9.61 KB
/
m2omf.def
File metadata and controls
288 lines (242 loc) · 9.61 KB
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
DEFINITION MODULE M2OMF;
(*
M2OMF.
This module provides a way of creating an OMF file as the end result of a
compile. Note that at the time of writing, it was written to support v2.1
of OMF.
The OMF file is created wholly in memory. The module does not write the file
out to disk unless explicitly told to do so by a call to FlushToDisk.
Note that this module does a lot of memory allocation and deallocation. It
does NOT use the standard libraries to do this, as they are not
comprehensive enough. We need to be able to extend a block as we need more
space. Only the GS Memory Manager provides this sort of functionality, so
direct calls to the MM are used.
*)
FROM MemoryManager IMPORT Handle;
FROM SYSTEM IMPORT ADDRESS, BYTE, WORD;
TYPE
aSegmentAttribute = (nul0, nul1, nul2, nul3, nul4, nul5, nul6, nul7,
atBankRelative, atSkipSegment, atReloadSegment,
atAbsoluteBank, atNoSpecialMemory, atPosIndependant,
atPrivate, atDynamic);
aSegmentAttributeSet = SET OF aSegmentAttribute;
aSegmentKind = (skCode, skData, skJumpTable, skNul3, skPathname, skNul5,
skNul6, skNul7, skLibraryDictionary, skNul9, skNul10,
skNul11, skNul12, skNul13, skNul14, skNul15,
skInitialisation, skNul17, skDirectPage);
pByte =
RECORD
CASE :CARDINAL OF
0: a: ADDRESS;
| 1: b: POINTER TO BYTE;
| 2: c: POINTER TO CHAR;
END;
END;
aSegmentHeader =
RECORD
BYTECNT: LONGCARD; (* Length of this segment (including header) in bytes *)
RESSPC: LONGCARD; (* Number of bytes of space to reserve after segment content *)
LENGTH: LONGCARD; (* Amount of memory required by segment *)
undefined: BYTE; (* reserved by Apple for future use *)
LABLEN: BYTE; (* number of bytes used by each label *)
NUMLEN: BYTE; (* number of bytes used by a number. MUST be 4 *)
VERSION: BYTE; (* OMF version number. Should be 2 *)
BANKSIZE: LONGCARD; (* max size of a segment. MUST be $10000 for code segments *)
CASE :BOOLEAN OF
TRUE: attributes: aSegmentAttributeSet; (* attributes of segment, bits 8 thru 15 *)
|
FALSE: KIND: CARDINAL; (* segment kind, bits 0 thru 7 *)
END;
undefined2: CARDINAL; (* reserved by Apple for future use *)
ORG: ADDRESS; (* absolute long address of the segment *)
ALIGN: LONGCARD; (* alignment of segment, $0, $100 or $10000 are legal *)
NUMSEX: BYTE; (* byte order, MUST be 0 *)
REVISION: BYTE; (* OMF revision number. Should be 1 *)
SEGNUM: CARDINAL; (* actual segment number *)
ENTRY: LONGCARD; (* offset into segment that is the entry point *)
DISPNAME: CARDINAL; (* displacement of the LOADNAME field *)
DISPDATA: CARDINAL; (* displacement of the segment data *)
tempORG: LONGCARD; (* temporary origin of segment *)
LOADNAME: ARRAY [0..9] OF CHAR; (* name of load segment *)
END;
pSegmentHeader = POINTER TO aSegmentHeader;
aOMFFileID =
RECORD
open: BOOLEAN; (* the file is open *)
fileName: ARRAY [0..79] OF CHAR; (* the file name *)
handle: Handle; (* the handle of the memory used by the file *)
size: LONGCARD; (* the size in bytes of the file *)
lastByte: ADDRESS; (* the last byte available in the file *)
segmentName: ARRAY [0..79] OF CHAR; (* the name of the current segment *)
segmentHeader: pSegmentHeader; (* ptr to the current segment header *)
segmentData: ADDRESS; (* address of first data byte of current segment *)
nextByte: pByte; (* address of next byte to be wrtten to *)
END;
aDisplacement = LONGCARD;
VAR
objFile: aOMFFileID;
PROCEDURE CloseOMFFile(discardFile: BOOLEAN;
saveToDisk: BOOLEAN);
(*
OPERATION:
This procedure closes the 'file' if it is open.
If discardFile is TRUE, then it simply disposes of any memory taken up
by the file.
If discardFile is FALSE, then saveToDisk is checked. If TRUE, the memory
file is written to disk. Finally, the 'file' is given to FastFile, which
leaves the file in memory, but removes it from our care.
*)
PROCEDURE DisposeOMFFile;
(*
OPERATION:
Dispose of any memory taken up by the 'file'. This would normaly only
be done if a compile error had occured.
*)
PROCEDURE EndSegment(kind: aSegmentKind; attr: aSegmentAttributeSet);
(*
OPERATION:
This procedure completes the current segment within the file by updating
the header accordingly.
*)
PROCEDURE FixLabel(labelNumber: CARDINAL);
(*
OPERATION:
This procedure is called when it is time to define the actual location of
a label. If there are any prior references to the label, then they are
back-patched accordingly.
*)
PROCEDURE GenData(label: ARRAY OF CHAR;
value: ADDRESS;
length: LONGCARD;
private: BOOLEAN);
(*
OPERATION:
This procedure will generate a label, and associated data.
'label' is the textual label associated with the data.
'value' contains the address of the first byte of the data.
'length' is the number of bytes of data.
'private' specifies whether to generate the label as being a private label.
*)
PROCEDURE GenDS(label: ARRAY OF CHAR;
length: LONGCARD;
private: BOOLEAN);
(*
OPERATION:
This procedure generates a label, and reserves 'length' bytes of space in
the form:
label DS length
The 'private' parameter specifies whether to generate the label as being
a private label.
*)
PROCEDURE GenGlobalOp(instruction: CARDINAL;
label: ARRAY OF CHAR;
offset: INTEGER;
shift: INTEGER;
width: CARDINAL);
(*
OPERATION:
This procedure will generate the OMF equivalent of an instruction. The
operand for the instruction is a label as defined by 'label'. An
optional offset to that label is supplied in 'offset'. 'width' defines
the number of bytes to be generated as a result of the expression. 'shift'
indicates that the result of the addition of the label and offset should
be shifted.
*)
PROCEDURE GenLocalOp(instruction: CARDINAL;
labelNumber: CARDINAL;
relative: BOOLEAN;
offset: INTEGER;
shift: BOOLEAN;
width: CARDINAL);
(*
OPERATION:
This procedure will generate the OMF equivalent of an instruction. The
operand for the instruction is a label as defined by 'labelNumber'. An
optional offset to that label is supplied in 'offset'. If 'relative' is
TRUE, then the operand is generated as a relative expression. 'width'
defines the number of bytes to be generated as a result of the expression.
'shift', if TRUE indicates that the operand should be shifted right 16
bits.
*)
PROCEDURE IncrementSegmentLength(bytes: LONGCARD);
(*
OPERATION:
Increments the length of the current segment by 'bytes'.
*)
PROCEDURE LabelDisplacement(labelNumber: CARDINAL): aDisplacement;
(*
OPERATION:
Returns the number of bytes between the current location within the current
segment, and the label specified by 'labelNumber'.
*)
PROCEDURE NewLabel(VAR labelNumber: CARDINAL);
(*
OPERATION:
This procedure returns the number of a new label. It assumes that the
label table has been initialised properly using 'InitialiseLabels' by
not doing any initialisation itself.
*)
PROCEDURE NewSegmentHeader(name: ARRAY OF CHAR);
(*
OPERATION:
This procedure will allocate a new segment header, and initialise it to be
a static code segment. The value of the "name" parameter is placed after
the header, and it's length is used to determine the actual size of the
header.
Any fields that have a value defined by Apple are filled in.
*)
PROCEDURE OpenNewOMFFile(name: ARRAY OF CHAR);
(*
OPERATION:
Allocate the initial chunk of memory for the file, and initialise the
OMFFileID accordingly.
*)
PROCEDURE PutByte(byte: BYTE);
(*
OPERATION:
Insert one byte into the file.
*)
PROCEDURE PutByteConstant(byte: BYTE);
(*
OPERATION:
Place a byte constant in the constant buffer.
*)
PROCEDURE PutLabelText(label: ARRAY OF CHAR);
(*
OPERATION:
Inserts the supplied label into the file, preceded by a length byte.
Note that this procedure does NOT use PutByte to insert each byte, for
performance reasons.
*)
PROCEDURE PutLong(long: LONGINT);
(*
OPERATION:
Insert four bytes into the file.
*)
PROCEDURE PutLongConstant(long: LONGINT);
(*
OPERATION:
Insert four bytes into the constant buffer.
*)
PROCEDURE PutWord(word: WORD);
(*
OPERATION:
Insert two bytes into the file.
*)
PROCEDURE PutWordConstant(word: WORD);
(*
OPERATION:
Insert two bytes in the constant buffer.
*)
PROCEDURE ReferenceLabel(labelNumber: CARDINAL);
(*
OPERATION:
This procedure generates a reference to the specified label. The reference
is 'inserted' at the current position in the 'file'. This means that:
o If the label hasn't been defined, then a label reference record is
created, that refers to the next byte in the file.
o If the label has been defined, then it's location is inserted starting
at the next byte in the file.
Both cases result in four bytes being allocated in the file.
*)
END M2OMF.