From d1fb15c154b99f9ca8d2356fa9057827b0ab89af Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 13 Nov 2007 09:37:59 -0800 Subject: Address data is int64_t; simplify writing an address object Address data is always int64_t even if the size itself is smaller; this was broken on bigendian hosts (still need testing!) Create simple "write sized object" macros. --- assemble.c | 17 ++++++----------- compiler.h | 11 +++++++++++ disasm.c | 2 +- float.c | 2 +- listing.c | 2 +- nasm.c | 4 ++-- nasmlib.c | 30 ++++++++++++++++-------------- nasmlib.h | 12 ++++++++++++ output/outaout.c | 6 +++--- output/outas86.c | 8 ++++---- output/outbin.c | 13 ++----------- output/outcoff.c | 8 ++++---- output/outdbg.c | 8 +------- output/outelf32.c | 6 +++--- output/outelf64.c | 8 ++++---- output/outieee.c | 2 +- output/outmacho.c | 9 ++------- output/outobj.c | 2 +- output/outrdf.c | 14 +++----------- output/outrdf2.c | 13 +++---------- 20 files changed, 81 insertions(+), 96 deletions(-) diff --git a/assemble.c b/assemble.c index a56887e..2d24e8d 100644 --- a/assemble.c +++ b/assemble.c @@ -181,18 +181,13 @@ static void out(int64_t offset, int32_t segto, const void *data, * convert it into RAWDATA format. */ uint8_t *q = p; - - switch (size) { - case 2: - WRITESHORT(q, *(int32_t *)data); - break; - case 4: - WRITELONG(q, *(int32_t *)data); - break; - case 8: - WRITEDLONG(q, *(int64_t *)data); - break; + + if (size > 8) { + errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8"); + return; } + + WRITEADDR(q, *(int64_t *)data, size); data = p; type = OUT_RAWDATA; } diff --git a/compiler.h b/compiler.h index 6e9e37e..b660855 100644 --- a/compiler.h +++ b/compiler.h @@ -96,4 +96,15 @@ int strnicmp(const char *, const char *, size_t); char *strsep(char **, const char *); #endif +/* + * Define this to 1 for faster performance if this is a littleendian + * platform which can do unaligned memory references. It is safe + * to leave it defined to 0 even if that is true. + */ +#if defined(__i386__) || defined(__x86_64__) +# define X86_MEMORY 1 +#else +# define X86_MEMORY 0 +#endif + #endif /* NASM_COMPILER_H */ diff --git a/disasm.c b/disasm.c index 139e8d2..18911f0 100644 --- a/disasm.c +++ b/disasm.c @@ -53,7 +53,7 @@ struct prefix_info { }; #define getu8(x) (*(uint8_t *)(x)) -#if defined(__i386__) || defined(__x86_64__) +#if X86_MEMORY /* Littleendian CPU which can handle unaligned references */ #define getu16(x) (*(uint16_t *)(x)) #define getu32(x) (*(uint32_t *)(x)) diff --git a/float.c b/float.c index eddb719..c4582cd 100644 --- a/float.c +++ b/float.c @@ -45,7 +45,7 @@ typedef uint64_t fp_2limb; #define LIMB_ALL_BYTES ((fp_limb)0x01010101) #define LIMB_BYTE(x) ((x)*LIMB_ALL_BYTES) -#if defined(__i386__) || defined(__x86_64__) +#if X86_MEMORY #define put(a,b) (*(uint32_t *)(a) = (b)) #else #define put(a,b) (((a)[0] = (b)), \ diff --git a/listing.c b/listing.c index 64ad348..e4da7cb 100644 --- a/listing.c +++ b/listing.c @@ -75,7 +75,7 @@ static void list_emit(void) if (listlinep) fprintf(listfp, " %s", listline); - fputc('\n', listfp); + putc('\n', listfp); listlinep = false; listdata[0] = '\0'; } diff --git a/nasm.c b/nasm.c index 880d0a5..95960bb 100644 --- a/nasm.c +++ b/nasm.c @@ -155,7 +155,7 @@ static void nasm_fputs(const char *line, FILE * outfile) { if (outfile) { fputs(line, outfile); - fputc('\n', outfile); + putc('\n', outfile); } else puts(line); } @@ -1608,7 +1608,7 @@ static void report_error_common(int severity, const char *fmt, } vfprintf(error_file, fmt, args); - fputc('\n', error_file); + putc('\n', error_file); if (severity & ERR_USAGE) want_usage = true; diff --git a/nasmlib.c b/nasmlib.c index 170c95f..b89c711 100644 --- a/nasmlib.c +++ b/nasmlib.c @@ -363,28 +363,30 @@ int32_t seg_alloc(void) void fwriteint16_t(int data, FILE * fp) { - fputc((int)(data & 255), fp); - fputc((int)((data >> 8) & 255), fp); + char buffer[2], *p = buffer; + WRITESHORT(p, data); + fwrite(buffer, 1, 2, fp); } void fwriteint32_t(int32_t data, FILE * fp) { - fputc((int)(data & 255), fp); - fputc((int)((data >> 8) & 255), fp); - fputc((int)((data >> 16) & 255), fp); - fputc((int)((data >> 24) & 255), fp); + char buffer[4], *p = buffer; + WRITELONG(p, data); + fwrite(buffer, 1, 4, fp); } void fwriteint64_t(int64_t data, FILE * fp) { - fputc((int)(data & 255), fp); - fputc((int)((data >> 8) & 255), fp); - fputc((int)((data >> 16) & 255), fp); - fputc((int)((data >> 24) & 255), fp); - fputc((int)((data >> 32) & 255), fp); - fputc((int)((data >> 40) & 255), fp); - fputc((int)((data >> 48) & 255), fp); - fputc((int)((data >> 56) & 255), fp); + char buffer[8], *p = buffer; + WRITEDLONG(p, data); + fwrite(buffer, 1, 8, fp); +} + +void fwriteaddr(int64_t data, int size, FILE * fp) +{ + char buffer[8], *p = buffer; + WRITEADDR(p, data, size); + fwrite(buffer, 1, size, fp); } void standard_extension(char *inname, char *outname, char *extension, diff --git a/nasmlib.h b/nasmlib.h index 560ec1e..2e18f10 100644 --- a/nasmlib.h +++ b/nasmlib.h @@ -209,12 +209,24 @@ void standard_extension(char *inname, char *outname, char *extension, WRITECHAR(p,(v) >> 56); \ } while (0) +#define WRITEADDR(p,v,s) \ + do { \ + int _s = (s); \ + uint64_t _v = (v); \ + while (_s--) { \ + WRITECHAR(p,_v); \ + _v >>= 8; \ + } \ + } while(0) + /* * and routines to do the same thing to a file */ +#define fwriteint8_t(d,f) putc(d,f) void fwriteint16_t(int data, FILE * fp); void fwriteint32_t(int32_t data, FILE * fp); void fwriteint64_t(int64_t data, FILE * fp); +void fwriteaddr(int64_t data, int size, FILE * fp); /* * Routines to manage a dynamic random access array of int32_ts which diff --git a/output/outaout.c b/output/outaout.c index a359b94..fec1262 100644 --- a/output/outaout.c +++ b/output/outaout.c @@ -622,7 +622,7 @@ static void aout_out(int32_t segto, const void *data, error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG"); aout_sect_write(s, data, size); } else if (type == OUT_ADDRESS) { - addr = *(int32_t *)data; + addr = *(int64_t *)data; if (segment != NO_SEG) { if (segment % 2) { error(ERR_NONFATAL, "a.out format does not support" @@ -699,7 +699,7 @@ static void aout_out(int32_t segto, const void *data, } } p = mydata; - WRITESHORT(p, *(int32_t *)data - (size + s->len)); + WRITESHORT(p, *(int64_t *)data - (size + s->len)); aout_sect_write(s, mydata, 2L); } else if (type == OUT_REL4ADR) { if (segment == segto) @@ -729,7 +729,7 @@ static void aout_out(int32_t segto, const void *data, } } p = mydata; - WRITELONG(p, *(int32_t *)data - (size + s->len)); + WRITELONG(p, *(int64_t *)data - (size + s->len)); aout_sect_write(s, mydata, 4L); } } diff --git a/output/outas86.c b/output/outas86.c index f342314..476e8c9 100644 --- a/output/outas86.c +++ b/output/outas86.c @@ -320,12 +320,12 @@ static void as86_out(int32_t segto, const void *data, error(ERR_NONFATAL, "as86 format does not support" " segment base references"); } else { - offset = *(int32_t *)data; + offset = *(int64_t *)data; as86_add_piece(s, 1, offset, segment, size, 0); } } else { p = mydata; - WRITELONG(p, *(int32_t *)data); + WRITELONG(p, *(int64_t *)data); as86_sect_write(s, data, size); as86_add_piece(s, 0, 0L, 0L, size, 0); } @@ -337,7 +337,7 @@ static void as86_out(int32_t segto, const void *data, error(ERR_NONFATAL, "as86 format does not support" " segment base references"); } else { - offset = *(int32_t *)data; + offset = *(int64_t *)data; as86_add_piece(s, 1, offset - size + 2, segment, 2L, 1); } @@ -350,7 +350,7 @@ static void as86_out(int32_t segto, const void *data, error(ERR_NONFATAL, "as86 format does not support" " segment base references"); } else { - offset = *(int32_t *)data; + offset = *(int64_t *)data; as86_add_piece(s, 1, offset - size + 4, segment, 4L, 1); } diff --git a/output/outbin.c b/output/outbin.c index d5ec3c7..68c5d95 100644 --- a/output/outbin.c +++ b/output/outbin.c @@ -788,12 +788,7 @@ static void bin_out(int32_t segto, const void *data, if (segment != NO_SEG) add_reloc(s, size, segment, -1L); p = mydata; - if (size == 4) - WRITELONG(p, *(int32_t *)data); - else if (size == 8) - WRITEDLONG(p, *(int64_t *)data); - else - WRITESHORT(p, *(int32_t *)data); + WRITEADDR(p, *(int64_t *)data, size); saa_wbytes(s->contents, mydata, size); } s->length += size; @@ -836,11 +831,7 @@ static void bin_out(int32_t segto, const void *data, if (s->flags & TYPE_PROGBITS) { add_reloc(s, size, segment, segto); p = mydata; - /* XXX: WHAT ABOUT SIZE == 8? */ - if (size == 4) - WRITELONG(p, *(int32_t *)data - size - s->length); - else - WRITESHORT(p, *(int32_t *)data - size - s->length); + WRITEADDR(p, *(int64_t *)data - size - s->length, size); saa_wbytes(s->contents, mydata, size); } s->length += size; diff --git a/output/outcoff.c b/output/outcoff.c index 95a1603..9be558b 100644 --- a/output/outcoff.c +++ b/output/outcoff.c @@ -533,7 +533,7 @@ static void coff_out(int32_t segto, const void *data, fix = coff_add_reloc(s, segment, false, false); } p = mydata; - WRITELONG(p, *(int32_t *)data + fix); + WRITELONG(p, *(int64_t *)data + fix); coff_sect_write(s, mydata, size); } } else { @@ -555,7 +555,7 @@ static void coff_out(int32_t segto, const void *data, coff_sect_write(s, mydata, size); } else { fix = coff_add_reloc(s, segment, false, false); - WRITELONG(p, *(int32_t *)data + fix); + WRITELONG(p, *(int64_t *)data + fix); coff_sect_write(s, mydata, size); } } @@ -577,9 +577,9 @@ static void coff_out(int32_t segto, const void *data, fix = coff_add_reloc(s, segment, true, false); p = mydata; if (win32 | win64) { - WRITELONG(p, *(int32_t *)data + 4 - size + fix); + WRITELONG(p, *(int64_t *)data + 4 - size + fix); } else { - WRITELONG(p, *(int32_t *)data - (size + s->len) + fix); + WRITELONG(p, *(int64_t *)data - (size + s->len) + fix); } coff_sect_write(s, mydata, 4L); } diff --git a/output/outdbg.c b/output/outdbg.c index 07e1b08..a139699 100644 --- a/output/outdbg.c +++ b/output/outdbg.c @@ -125,13 +125,7 @@ static void dbg_out(int32_t segto, const void *data, fprintf(dbgf, "\n"); break; case OUT_ADDRESS: - ldata = 0; /* placate gcc */ - if (size == 1) - ldata = *((char *)data); - else if (size == 2) - ldata = *((int16_t *)data); - else if (size == 4) - ldata = *((int32_t *)data); + ldata = *(int64_t *)data; fprintf(dbgf, "addr %08lx (seg %08lx, wrt %08lx)\n", ldata, segment, wrt); break; diff --git a/output/outelf32.c b/output/outelf32.c index 8599a65..4976942 100644 --- a/output/outelf32.c +++ b/output/outelf32.c @@ -841,7 +841,7 @@ static void elf_out(int32_t segto, const void *data, elf_sect_write(s, data, size); } else if (type == OUT_ADDRESS) { bool gnu16 = false; - addr = *(int32_t *)data; + addr = *(int64_t *)data; if (segment != NO_SEG) { if (segment % 2) { error(ERR_NONFATAL, "ELF format does not support" @@ -916,7 +916,7 @@ static void elf_out(int32_t segto, const void *data, } } p = mydata; - WRITESHORT(p, *(int32_t *)data - size); + WRITESHORT(p, *(int64_t *)data - size); elf_sect_write(s, mydata, 2L); } else if (type == OUT_REL4ADR) { if (segment == segto) @@ -941,7 +941,7 @@ static void elf_out(int32_t segto, const void *data, } } p = mydata; - WRITELONG(p, *(int32_t *)data - size); + WRITELONG(p, *(int64_t *)data - size); elf_sect_write(s, mydata, 4L); } } diff --git a/output/outelf64.c b/output/outelf64.c index d364268..dcf3def 100644 --- a/output/outelf64.c +++ b/output/outelf64.c @@ -798,8 +798,8 @@ static void elf_out(int32_t segto, const void *data, #if defined(DEBUG) && DEBUG>2 fprintf(stderr, - " elf_out type: %x seg: %d bytes: %x data: %x\n", - (type >> 24), segment, size, *(int32_t *)data); + " elf_out type: %x seg: %d bytes: %x data: %"PRIx64"\n", + (type >> 24), segment, size, *(int64_t *)data); #endif /* @@ -951,7 +951,7 @@ static void elf_out(int32_t segto, const void *data, } } p = mydata; - WRITESHORT(p, *(int32_t *)data - size); + WRITESHORT(p, *(int64_t *)data - size); elf_sect_write(s, mydata, 2L); } else if (type == OUT_REL4ADR) { if (segment == segto) @@ -976,7 +976,7 @@ static void elf_out(int32_t segto, const void *data, } } p = mydata; - WRITELONG(p, *(int32_t *)data - size); + WRITELONG(p, *(int64_t *)data - size); elf_sect_write(s, mydata, 4L); } } diff --git a/output/outieee.c b/output/outieee.c index 431a6d8..93a27b5 100644 --- a/output/outieee.c +++ b/output/outieee.c @@ -418,7 +418,7 @@ static void ieee_out(int32_t segto, const void *data, if (segment == NO_SEG && type != OUT_ADDRESS) error(ERR_NONFATAL, "relative call to absolute address not" " supported by IEEE format"); - ldata = *(int32_t *)data; + ldata = *(int64_t *)data; if (type == OUT_REL2ADR) ldata += (size - 2); if (type == OUT_REL4ADR) diff --git a/output/outmacho.c b/output/outmacho.c index 802ea97..14633f4 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -464,7 +464,7 @@ static void macho_output(int32_t secto, const void *data, break; case OUT_ADDRESS: - addr = *(int32_t *)data; + addr = *(int64_t *)data; if (section != NO_SEG) { if (section % 2) { @@ -475,12 +475,7 @@ static void macho_output(int32_t secto, const void *data, } p = mydata; - - if (size == 2) - WRITESHORT(p, addr); - else - WRITELONG(p, addr); - + WRITEADDR(p, addr, size); sect_write(s, mydata, size); break; diff --git a/output/outobj.c b/output/outobj.c index 95339e2..3dfbf96 100644 --- a/output/outobj.c +++ b/output/outobj.c @@ -1061,7 +1061,7 @@ static void obj_out(int32_t segto, const void *data, if (segment >= SEG_ABS) error(ERR_NONFATAL, "far-absolute relocations not supported" " by OBJ format"); - ldata = *(int32_t *)data; + ldata = *(int64_t *)data; if (type == OUT_REL2ADR) { ldata += (size - 2); size = 2; diff --git a/output/outrdf.c b/output/outrdf.c index 23e661e..9c3785b 100644 --- a/output/outrdf.c +++ b/output/outrdf.c @@ -392,16 +392,8 @@ static void rdf_out(int32_t segto, void *data, uint32_t type, } pd = databuf; /* convert address to little-endian */ - if (bytes == 4) - WRITELONG(pd, *(int32_t *)data); - else if (bytes == 8) - WRITEDLONG(pd, *(int64_t *)data); - else - WRITESHORT(pd, *(int32_t *)data); - - + WRITEADDR(pd, *(int64_t *)data, bytes); membufwrite(seg[segto], databuf, bytes); - } else if (type == OUT_REL2ADR) { if (segment == segto) error(ERR_PANIC, "intra-segment OUT_REL2ADR"); @@ -422,7 +414,7 @@ static void rdf_out(int32_t segto, void *data, uint32_t type, * address of imported symbol onto it to get address relative to end of * instruction: import_address + data(offset) - end_of_instrn */ - rr.offset = *(int32_t *)data - (rr.offset + bytes); + rr.offset = *(int64_t *)data - (rr.offset + bytes); membufwrite(seg[segto], &rr.offset, -2); } else if (type == OUT_REL4ADR) { @@ -440,7 +432,7 @@ static void rdf_out(int32_t segto, void *data, uint32_t type, rr.refseg = segment; /* segment referred to */ write_reloc_rec(&rr); - rr.offset = *(int32_t *)data - (rr.offset + bytes); + rr.offset = *(int64_t *)data - (rr.offset + bytes); membufwrite(seg[segto], &rr.offset, -4); } } diff --git a/output/outrdf2.c b/output/outrdf2.c index 980d113..5bc00d5 100644 --- a/output/outrdf2.c +++ b/output/outrdf2.c @@ -583,15 +583,8 @@ static void rdf2_out(int32_t segto, const void *data, } pd = databuf; /* convert address to little-endian */ - if (size == 4) - WRITESHORT(pd, *(int32_t *)data); - else if (size == 8) - WRITEDLONG(pd, *(int64_t *)data); - else - WRITESHORT(pd, *(int32_t *)data); - + WRITEADDR(pd, *(int64_t *)data, size); membufwrite(segto, databuf, size); - } else if (type == OUT_REL2ADR) { if (segment == segto) error(ERR_PANIC, "intra-segment OUT_REL2ADR"); @@ -609,7 +602,7 @@ static void rdf2_out(int32_t segto, const void *data, /* what do we put in the code? Simply the data. This should almost * always be zero, unless someone's doing segment arithmetic... */ - rr.offset = *(int32_t *)data; + rr.offset = *(int64_t *)data; } else { rr.type = RDFREC_RELOC; /* type signature */ rr.segment = segto + 64; /* segment we're currently in + rel flag */ @@ -639,7 +632,7 @@ static void rdf2_out(int32_t segto, const void *data, rr.reclen = 8; write_reloc_rec(&rr); - rr.offset = *(int32_t *)data - (rr.offset + size); + rr.offset = *(int64_t *)data - (rr.offset + size); membufwrite(segto, &rr.offset, -4); } -- cgit v1.2.3