]>
git.saurik.com Git - apple/boot.git/blob - i386/nasm/outas86.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* outas86.c output routines for the Netwide Assembler to produce
25 * Linux as86 (bin86-0.3) object files
27 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
28 * Julian Hall. All rights reserved. The software is
29 * redistributable under the licence given in the file "Licence"
30 * distributed in the NASM archive.
46 int type
; /* 0 = absolute, 1 = seg, 2 = sym */
47 long offset
; /* relative offset */
48 int number
; /* symbol/segment number (4=bss) */
49 long bytes
; /* size of reloc or of absolute data */
50 int relative
; /* TRUE or FALSE */
54 long strpos
; /* string table position of name */
55 int flags
; /* symbol flags */
56 int segment
; /* 4=bss at this point */
57 long value
; /* address, or COMMON variable size */
61 * Section IDs - used in Piece.number and Symbol.segment.
63 #define SECT_TEXT 0 /* text section */
64 #define SECT_DATA 3 /* data section */
65 #define SECT_BSS 4 /* bss section */
68 * Flags used in Symbol.flags.
70 #define SYM_ENTRY (1<<8)
71 #define SYM_EXPORT (1<<7)
72 #define SYM_IMPORT (1<<6)
73 #define SYM_ABSOLUTE (1<<4)
77 unsigned long datalen
, size
, len
;
79 struct Piece
*head
, *last
, **tail
;
82 static char as86_module
[FILENAME_MAX
];
84 static struct Section stext
, sdata
;
85 static unsigned long bsslen
;
88 static struct SAA
*syms
;
89 static unsigned long nsyms
;
91 static struct RAA
*bsym
;
93 static struct SAA
*strs
;
94 static unsigned long strslen
;
96 static int as86_reloc_size
;
101 static void as86_write(void);
102 static void as86_write_section (struct Section
*, int);
103 static int as86_add_string (char *name
);
104 static void as86_sect_write(struct Section
*, unsigned char *, unsigned long);
106 static void as86_init(FILE *fp
, efunc errfunc
, ldfunc ldef
, evalfunc eval
) {
109 (void) ldef
; /* placate optimisers */
110 stext
.data
= saa_init(1L); stext
.datalen
= 0L;
111 stext
.head
= stext
.last
= NULL
;
112 stext
.tail
= &stext
.head
;
113 sdata
.data
= saa_init(1L); sdata
.datalen
= 0L;
114 sdata
.head
= sdata
.last
= NULL
;
115 sdata
.tail
= &sdata
.head
;
117 stext
.len
= stext
.datalen
= stext
.size
=
118 sdata
.len
= sdata
.datalen
= sdata
.size
= 0;
119 stext
.index
= seg_alloc();
120 sdata
.index
= seg_alloc();
121 bssindex
= seg_alloc();
122 syms
= saa_init((long)sizeof(struct Symbol
));
128 as86_add_string (as86_module
);
131 static void as86_cleanup(void) {
136 saa_free (stext
.data
);
139 stext
.head
= stext
.head
->next
;
142 saa_free (sdata
.data
);
145 sdata
.head
= sdata
.head
->next
;
153 static long as86_section_names (char *name
, int pass
, int *bits
) {
155 * Default is 16 bits.
163 if (!strcmp(name
, ".text"))
165 else if (!strcmp(name
, ".data"))
167 else if (!strcmp(name
, ".bss"))
173 static int as86_add_string (char *name
) {
175 int length
= strlen(name
);
177 saa_wbytes (strs
, name
, (long)(length
+1));
183 static void as86_deflabel (char *name
, long segment
, long offset
,
184 int is_global
, char *special
) {
188 error (ERR_NONFATAL
, "as86 format does not support any"
189 " special symbol types");
191 if (name
[0] == '.' && name
[1] == '.' && name
[2] != '@') {
192 error (ERR_NONFATAL
, "unrecognised special symbol `%s'", name
);
196 sym
= saa_wstruct (syms
);
198 sym
->strpos
= as86_add_string (name
);
200 if (segment
== NO_SEG
)
201 sym
->flags
|= SYM_ABSOLUTE
, sym
->segment
= 0;
202 else if (segment
== stext
.index
)
203 sym
->segment
= SECT_TEXT
;
204 else if (segment
== sdata
.index
)
205 sym
->segment
= SECT_DATA
;
206 else if (segment
== bssindex
)
207 sym
->segment
= SECT_BSS
;
209 sym
->flags
|= SYM_IMPORT
;
214 sym
->segment
= 3; /* already have IMPORT */
216 if (is_global
&& !(sym
->flags
& SYM_IMPORT
))
217 sym
->flags
|= SYM_EXPORT
;
222 * define the references from external-symbol segment numbers
223 * to these symbol records.
225 if (segment
!= NO_SEG
&& segment
!= stext
.index
&&
226 segment
!= sdata
.index
&& segment
!= bssindex
)
227 bsym
= raa_write (bsym
, segment
, nsyms
);
232 static void as86_add_piece (struct Section
*sect
, int type
, long offset
,
233 long segment
, long bytes
, int relative
) {
238 if (type
== 0 && sect
->last
&& sect
->last
->type
== 0) {
239 sect
->last
->bytes
+= bytes
;
243 p
= sect
->last
= *sect
->tail
= nasm_malloc(sizeof(struct Piece
));
244 sect
->tail
= &p
->next
;
250 p
->relative
= relative
;
252 if (type
== 1 && segment
== stext
.index
)
253 p
->number
= SECT_TEXT
;
254 else if (type
== 1 && segment
== sdata
.index
)
255 p
->number
= SECT_DATA
;
256 else if (type
== 1 && segment
== bssindex
)
257 p
->number
= SECT_BSS
;
259 p
->number
= raa_read (bsym
, segment
), p
->type
= 2;
262 static void as86_out (long segto
, void *data
, unsigned long type
,
263 long segment
, long wrt
) {
265 long realbytes
= type
& OUT_SIZMASK
;
267 unsigned char mydata
[4], *p
;
270 wrt
= NO_SEG
; /* continue to do _something_ */
271 error (ERR_NONFATAL
, "WRT not supported by as86 output format");
277 * handle absolute-assembly (structure definitions)
279 if (segto
== NO_SEG
) {
280 if (type
!= OUT_RESERVE
)
281 error (ERR_NONFATAL
, "attempt to assemble code in [ABSOLUTE]"
286 if (segto
== stext
.index
)
288 else if (segto
== sdata
.index
)
290 else if (segto
== bssindex
)
293 error(ERR_WARNING
, "attempt to assemble code in"
294 " segment %d: defaulting to `.text'", segto
);
298 if (!s
&& type
!= OUT_RESERVE
) {
299 error(ERR_WARNING
, "attempt to initialise memory in the"
300 " BSS section: ignored");
301 if (type
== OUT_REL2ADR
)
303 else if (type
== OUT_REL4ADR
)
309 if (type
== OUT_RESERVE
) {
311 error(ERR_WARNING
, "uninitialised space declared in"
312 " %s section: zeroing",
313 (segto
== stext
.index
? "code" : "data"));
314 as86_sect_write (s
, NULL
, realbytes
);
315 as86_add_piece (s
, 0, 0L, 0L, realbytes
, 0);
318 } else if (type
== OUT_RAWDATA
) {
319 if (segment
!= NO_SEG
)
320 error(ERR_PANIC
, "OUT_RAWDATA with other than NO_SEG");
321 as86_sect_write (s
, data
, realbytes
);
322 as86_add_piece (s
, 0, 0L, 0L, realbytes
, 0);
323 } else if (type
== OUT_ADDRESS
) {
324 if (segment
!= NO_SEG
) {
326 error(ERR_NONFATAL
, "as86 format does not support"
327 " segment base references");
329 offset
= * (long *) data
;
330 as86_add_piece (s
, 1, offset
, segment
, realbytes
, 0);
334 WRITELONG (p
, * (long *) data
);
335 as86_sect_write (s
, data
, realbytes
);
336 as86_add_piece (s
, 0, 0L, 0L, realbytes
, 0);
338 } else if (type
== OUT_REL2ADR
) {
339 if (segment
== segto
)
340 error(ERR_PANIC
, "intra-segment OUT_REL2ADR");
341 if (segment
!= NO_SEG
) {
343 error(ERR_NONFATAL
, "as86 format does not support"
344 " segment base references");
346 offset
= * (long *) data
;
347 as86_add_piece (s
, 1, offset
-realbytes
+2, segment
, 2L, 1);
350 } else if (type
== OUT_REL4ADR
) {
351 if (segment
== segto
)
352 error(ERR_PANIC
, "intra-segment OUT_REL4ADR");
353 if (segment
!= NO_SEG
) {
355 error(ERR_NONFATAL
, "as86 format does not support"
356 " segment base references");
358 offset
= * (long *) data
;
359 as86_add_piece (s
, 1, offset
-realbytes
+4, segment
, 4L, 1);
365 static void as86_write(void) {
367 long symlen
, seglen
, segsize
;
370 * First, go through the symbol records working out how big
371 * each will be. Also fix up BSS references at this time, and
372 * set the flags words up completely.
376 for (i
= 0; i
< nsyms
; i
++) {
377 struct Symbol
*sym
= saa_rstruct (syms
);
378 if (sym
->segment
== SECT_BSS
)
379 sym
->segment
= SECT_DATA
, sym
->value
+= sdata
.len
;
380 sym
->flags
|= sym
->segment
;
382 sym
->flags
|= 0 << 14, symlen
+= 4;
383 else if (sym
->value
>= 0 && sym
->value
<= 255)
384 sym
->flags
|= 1 << 14, symlen
+= 5;
385 else if (sym
->value
>= 0 && sym
->value
<= 65535L)
386 sym
->flags
|= 2 << 14, symlen
+= 6;
388 sym
->flags
|= 3 << 14, symlen
+= 8;
392 * Now do the same for the segments, and get the segment size
393 * descriptor word at the same time.
395 seglen
= segsize
= 0;
396 if ((unsigned long) stext
.len
> 65535L)
397 segsize
|= 0x03000000L
, seglen
+= 4;
399 segsize
|= 0x02000000L
, seglen
+= 2;
400 if ((unsigned long) sdata
.len
> 65535L)
401 segsize
|= 0xC0000000L
, seglen
+= 4;
403 segsize
|= 0x80000000L
, seglen
+= 2;
406 * Emit the as86 header.
408 fwritelong (0x000186A3L
, as86fp
);
409 fputc (0x2A, as86fp
);
410 fwritelong (27+symlen
+seglen
+strslen
, as86fp
); /* header length */
411 fwritelong (stext
.len
+sdata
.len
, as86fp
);
412 fwriteshort (strslen
, as86fp
);
413 fwriteshort (0, as86fp
); /* class = revision = 0 */
414 fwritelong (0x55555555L
, as86fp
); /* segment max sizes: always this */
415 fwritelong (segsize
, as86fp
); /* segment size descriptors */
416 if (segsize
& 0x01000000L
)
417 fwritelong (stext
.len
, as86fp
);
419 fwriteshort (stext
.len
, as86fp
);
420 if (segsize
& 0x40000000L
)
421 fwritelong (sdata
.len
, as86fp
);
423 fwriteshort (sdata
.len
, as86fp
);
424 fwriteshort (nsyms
, as86fp
);
427 * Write the symbol table.
430 for (i
= 0; i
< nsyms
; i
++) {
431 struct Symbol
*sym
= saa_rstruct (syms
);
432 fwriteshort (sym
->strpos
, as86fp
);
433 fwriteshort (sym
->flags
, as86fp
);
434 switch (sym
->flags
& (3<<14)) {
436 case 1<<14: fputc (sym
->value
, as86fp
); break;
437 case 2<<14: fwriteshort (sym
->value
, as86fp
); break;
438 case 3<<14: fwritelong (sym
->value
, as86fp
); break;
443 * Write out the string table.
445 saa_fpwrite (strs
, as86fp
);
448 * Write the program text.
450 as86_reloc_size
= -1;
451 as86_write_section (&stext
, SECT_TEXT
);
452 as86_write_section (&sdata
, SECT_DATA
);
453 fputc (0, as86fp
); /* termination */
456 static void as86_set_rsize (int size
) {
457 if (as86_reloc_size
!= size
) {
458 switch (as86_reloc_size
= size
) {
459 case 1: fputc (0x01, as86fp
); break;
460 case 2: fputc (0x02, as86fp
); break;
461 case 4: fputc (0x03, as86fp
); break;
462 default: error (ERR_PANIC
, "bizarre relocation size %d", size
);
467 static void as86_write_section (struct Section
*sect
, int index
) {
472 fputc (0x20+index
, as86fp
); /* select the right section */
474 saa_rewind (sect
->data
);
476 for (p
= sect
->head
; p
; p
= p
->next
)
480 * Absolute data. Emit it in chunks of at most 64
486 long tmplen
= (length
> 64 ? 64 : length
);
487 fputc (0x40 | (tmplen
& 0x3F), as86fp
);
488 saa_rnbytes (sect
->data
, buf
, tmplen
);
489 fwrite (buf
, 1, tmplen
, as86fp
);
491 } while (length
> 0);
495 * A segment-type relocation. First fix up the BSS.
497 if (p
->number
== SECT_BSS
)
498 p
->number
= SECT_DATA
, p
->offset
+= sdata
.len
;
499 as86_set_rsize (p
->bytes
);
500 fputc (0x80 | (p
->relative
? 0x20 : 0) | p
->number
, as86fp
);
501 if (as86_reloc_size
== 2)
502 fwriteshort (p
->offset
, as86fp
);
504 fwritelong (p
->offset
, as86fp
);
508 * A symbol-type relocation.
510 as86_set_rsize (p
->bytes
);
521 (p
->relative
? 0x20 : 0) |
522 (p
->number
> 255 ? 0x04 : 0) | s
, as86fp
);
524 fwriteshort (p
->number
, as86fp
);
526 fputc (p
->number
, as86fp
);
529 case 1: fputc (p
->offset
, as86fp
); break;
530 case 2: fwriteshort (p
->offset
, as86fp
); break;
531 case 3: fwritelong (p
->offset
, as86fp
); break;
537 static void as86_sect_write (struct Section
*sect
,
538 unsigned char *data
, unsigned long len
) {
539 saa_wbytes (sect
->data
, data
, len
);
540 sect
->datalen
+= len
;
543 static long as86_segbase (long segment
) {
547 static int as86_directive (char *directive
, char *value
, int pass
) {
551 static void as86_filename (char *inname
, char *outname
, efunc error
) {
554 if ( (p
= strrchr (inname
, '.')) != NULL
) {
555 strncpy (as86_module
, inname
, p
-inname
);
556 as86_module
[p
-inname
] = '\0';
558 strcpy (as86_module
, inname
);
560 standard_extension (inname
, outname
, ".o", error
);
563 static char *as86_stdmac
[] = {
564 "%define __SECT__ [section .text]",
568 struct ofmt of_as86
= {
569 "Linux as86 (bin86 version 0.3) object files",