diff options
Diffstat (limited to 'as')
-rw-r--r-- | as/Makefile | 2 | ||||
-rw-r--r-- | as/align.h | 23 | ||||
-rw-r--r-- | as/as.c | 2 | ||||
-rw-r--r-- | as/as86_encap.sh | 1 | ||||
-rw-r--r-- | as/byteord.h | 6 | ||||
-rw-r--r-- | as/const.h | 14 | ||||
-rw-r--r-- | as/express.c | 10 | ||||
-rw-r--r-- | as/table.c | 2 | ||||
-rw-r--r-- | as/typeconv.c | 578 | ||||
-rw-r--r-- | as/typeconv.c.old | 537 |
10 files changed, 694 insertions, 481 deletions
diff --git a/as/Makefile b/as/Makefile index 4319371..04a0d98 100644 --- a/as/Makefile +++ b/as/Makefile @@ -23,7 +23,7 @@ install: all install -d $(LIBDIR) install -m 755 as86 $(LIBDIR) install -d $(BINDIR) - install -m 755 tmp $(BINDIR)/as86_encap + install -m 755 as86_encap $(BINDIR)/as86_encap -@rm -f tmp clean realclean: diff --git a/as/align.h b/as/align.h new file mode 100644 index 0000000..52b1e89 --- /dev/null +++ b/as/align.h @@ -0,0 +1,23 @@ +/* align.h - memory alignment requirements for linker */ + +/* Copyright (C) 1994 Bruce Evans */ + +#ifndef S_ALIGNMENT +# define align(x) +#else + +#if defined(__STDC__) && defined(_POSIX_SOURCE) +# define align(x) ((x)=(void *) \ + (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) +#else +# define align(x) ((x)=(void *) \ + ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1)))) +#endif +#endif + + + + + + + @@ -62,7 +62,7 @@ char **argv; initbin(); initobj(); initsource(); /* only nec to init for unsupported mem file */ - typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); + typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); as_warn.global = TRUE; /* constant */ last_pass=1; process_args(argc, argv); diff --git a/as/as86_encap.sh b/as/as86_encap.sh index 0ba4e71..5dea514 100644 --- a/as/as86_encap.sh +++ b/as/as86_encap.sh @@ -21,6 +21,7 @@ trap "rm -f _$$.* ; exit 99" 1 2 3 15 LIBDIR='%%LIBDIR%%' # Set by make install # If the one set by install fails then try a couple of others. +[ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`" [ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`/../lib" [ -x "$LIBDIR/as86" ] || LIBDIR=/usr/bin diff --git a/as/byteord.h b/as/byteord.h index a0d14e1..baf02d0 100644 --- a/as/byteord.h +++ b/as/byteord.h @@ -3,16 +3,16 @@ /* These are for the targets of everything and for linker source too. */ #ifdef I8086 -# define BIG_ENDIAN 0 +# define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ #endif #ifdef I80386 -# define BIG_ENDIAN 0 +# define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 #endif #ifdef MC6809 -# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif @@ -2,20 +2,12 @@ /* Speed and space hacks for BCC */ #ifdef __AS386_16__ #define LOW_BYTE 0 /* must be changed for big-endian */ -#define align(x) /* Don't bother */ +#else +#define S_ALIGNMENT sizeof(long) #endif -#ifndef align -#ifdef MSDOS -#define align(x) -#endif -#endif - -#ifndef align /* Normal ... */ -#define align(x) ((x) = (void*)(((long) (x) + (4-1)) & ~(4-1))) -#endif - +#include "align.h" /* const.h - constants for assembler */ diff --git a/as/express.c b/as/express.c index 0bcd8b4..023e2dd 100644 --- a/as/express.c +++ b/as/express.c @@ -330,6 +330,16 @@ PUBLIC void factor() chkabs(); lastexp.offset = ~lastexp.offset; return; + case ADDOP: + getsym(); + factor(); + return; + case SUBOP: + getsym(); + factor(); + chkabs(); + lastexp.offset = -lastexp.offset; + return; case STAR: /* context-sensitive, STAR means location counter here */ lastexp.offset = lc; @@ -180,7 +180,7 @@ PUBLIC struct sym_s *lookup() symptr->type = 0; symptr->data = inidata; symptr->length = length; - symptr->value_reg_or_op.value = (unsigned) (symptr->next = NUL_PTR); + symptr->value_reg_or_op.value = (offset_t) (symptr->next = NUL_PTR); heapptr = symptr->name; do *heapptr++ = *nameptr++; diff --git a/as/typeconv.c b/as/typeconv.c index c51b991..6cc4a20 100644 --- a/as/typeconv.c +++ b/as/typeconv.c @@ -1,537 +1,187 @@ -/* typeconv.c - convert between char arrays and unsigneds */ - -/* Copyright (C) 1994 Bruce Evans */ /* - c2u2(): 2 byte array to 2 byte unsigned - c4u4(): 4 byte array to 4 byte unsigned - cnu2(): n byte array to 2 byte unsigned - cnu4(): n byte array to 4 byte unsigned - u2c2(): 2 byte unsigned to 2 byte array - u2cn(): 2 byte unsigned to n byte array - u4c4(): 4 byte unsigned to 4 byte array - u4cn(): 4 byte unsigned to n byte array - typeconv_init: (re)initialise for given byte order. - Default is no swapping, but the initialisation should be done - anyway to provide some validity checks (returns FALSE if error). - - Not provided: - c2u4(), c4u2(), u2c4(), u4c2(). - Each of these is best done by truncating or extending a return value - or argument to the appropiate fixed-count function. - c4u2() has too many cases to do in-line conveniently, and the others - are hardly more efficient when done in-line. - - 4 byte orderings for both char arrays and unsigneds are supported: - 0123 - little-endian - 3210 - big-endian - 2301 - little-endian with long words big-endian (pdp11) - 1032 - big-endian with long words little_endian (who knows?) - - The unsigned's byte order is that of the machine on which these - routines are running. - It is determined at run time initialisation since the compiler/ - preprocessor is too dumb to tell us at compile time. -*/ + * Type conversion routines, these have been rewritten for portability. + * + * The only requirement is now that the u2_t and u4_t must be big enough. + */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" -FORWARD u2_pt c2u2_00 P((char *buf)); -FORWARD u4_pt c4u4_00 P((char *buf)); -FORWARD u2_pt c2u2_ss P((char *buf)); -FORWARD u4_pt c4u4_ss P((char *buf)); -FORWARD u4_pt c4u4_s0 P((char *buf)); -FORWARD u4_pt c4u4_0s P((char *buf)); -FORWARD void u2c2_00 P((char *buf, u2_pt offset)); -FORWARD void u4c4_00 P((char *buf, u4_t offset)); -FORWARD void u2c2_ss P((char *buf, u2_pt offset)); -FORWARD void u4c4_ss P((char *buf, u4_t offset)); -FORWARD void u4c4_s0 P((char *buf, u4_t offset)); -FORWARD void u4c4_0s P((char *buf, u4_t offset)); - -PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; -PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; -PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; -PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; - -/* === char arrays to unsigneds === */ - -/* no bytes swapped, longwinded to avoid alignment problems */ - -PRIVATE u2_pt c2u2_00(buf) -register char *buf; -{ - u2_t offset; - - ((char *) &offset)[0] = buf[0]; - ((char *) &offset)[1] = buf[1]; - return offset; -} - -PRIVATE u4_pt c4u4_00(buf) -register char *buf; -{ - u4_t offset; +void xxerr P((char *)); +void xxerr(x) char * x; { write(2, x, strlen(x)); } - ((char *) &offset)[0] = buf[0]; - ((char *) &offset)[1] = buf[1]; - ((char *) &offset)[2] = buf[2]; - ((char *) &offset)[3] = buf[3]; - return offset; -} - -/* straight swapping for little-endian to big-endian and vice versa */ - -PRIVATE u2_pt c2u2_ss(buf) -register char *buf; -{ - u2_t offset; - - ((char *) &offset)[0] = buf[1]; - ((char *) &offset)[1] = buf[0]; - return offset; -} - -PRIVATE u4_pt c4u4_ss(buf) -register char *buf; -{ - u4_t offset; - - ((char *) &offset)[0] = buf[3]; - ((char *) &offset)[1] = buf[2]; - ((char *) &offset)[2] = buf[1]; - ((char *) &offset)[3] = buf[0]; - return offset; -} +static int no_swap = 1; -/* wierd swapping for different-endian u2's, same-endian u4's */ +static long_off[4] = {0,1,2,3}; +static int_off[2] = {0,1}; -PRIVATE u4_pt c4u4_s0(buf) -register char *buf; +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; { - u4_t offset; + int i; + no_swap = (!big_endian && !long_big_endian); - ((char *) &offset)[0] = buf[1]; - ((char *) &offset)[1] = buf[0]; - ((char *) &offset)[2] = buf[3]; - ((char *) &offset)[3] = buf[2]; - return offset; -} - -/* very wierd swapping for same-endian u2's, different-endian u4's */ + for(i=0; i<4; i++) long_off[i] = i; + for(i=0; i<2; i++) int_off[i] = i; -PRIVATE u4_pt c4u4_0s(buf) -register char *buf; -{ - u4_t offset; + if( long_big_endian ) + { + i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i; + i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i; + } + if( big_endian ) + { + i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i; + i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i; - ((char *) &offset)[0] = buf[2]; - ((char *) &offset)[1] = buf[3]; - ((char *) &offset)[2] = buf[0]; - ((char *) &offset)[3] = buf[1]; - return offset; + i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; + } + return 1; } -/* === entry points === */ - -PUBLIC u2_pt c2u2(buf) +PUBLIC void u2c2(buf, offset) char *buf; +u2_pt offset; { - return (*pc2u2) (buf); +#ifdef __AS386_16__ + if( no_swap ) + { + *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */ + return; + } +#endif + buf[int_off[0]] = offset; + buf[int_off[1]] = (offset>>8); } -PUBLIC u4_t c4u4(buf) +PUBLIC void u4c4(buf, offset) char *buf; +u4_t offset; { - return (*pc4u4) (buf); + int i; +#ifdef __AS386_16__ + if( no_swap ) + { + *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */ + return; + } +#endif + for(i=0; i<4; i++) + { + buf[long_off[i]] = offset; + offset >>= 8; + } } -PUBLIC u2_pt cnu2(buf, count) +PUBLIC void u4cn(buf, offset, count) char *buf; +u4_t offset; unsigned count; { - switch (count) + switch(count) { case 1: - return buf[0] & 0xFF; + buf[0] = (char) offset; + return; case 2: - return (*pc2u2) (buf); + u2c2(buf, (u2_pt) offset); + return; case 4: - return (u2_pt) (*pc4u4) (buf); + u4c4(buf, (u4_t) offset); + return; default: - return 0; + xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); + return; } } -PUBLIC u4_t cnu4(buf, count) +PUBLIC void u2cn(buf, offset, count) char *buf; +u2_pt offset; unsigned count; { - switch (count) + switch(count) { case 1: - return buf[0] & 0xFF; + buf[0] = (char) offset; + return; case 2: - return (*pc2u2) (buf); + u2c2(buf, (u2_pt) offset); + return; case 4: - return (*pc4u4) (buf); + u4c4(buf, (u4_t) offset); + return; default: - return 0; + xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); + return; } } -/* === unsigneds to char arrays === */ - -/* no bytes swapped, longwinded to avoid alignment problems */ - -PRIVATE void u2c2_00(buf, offset) -register char *buf; -u2_pt offset; -{ - - buf[0] = ((char *) &offset)[0]; - buf[1] = ((char *) &offset)[1]; -} - -PRIVATE void u4c4_00(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[0]; - buf[1] = ((char *) &offset)[1]; - buf[2] = ((char *) &offset)[2]; - buf[3] = ((char *) &offset)[3]; -} - -/* straight swapping for little-endian to big-endian and vice versa */ - -PRIVATE void u2c2_ss(buf, offset) -register char *buf; -u2_pt offset; -{ - u2_t offset2; - - offset2 = offset; - buf[0] = ((char *) &offset2)[1]; - buf[1] = ((char *) &offset2)[0]; -} - -PRIVATE void u4c4_ss(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[3]; - buf[1] = ((char *) &offset)[2]; - buf[2] = ((char *) &offset)[1]; - buf[3] = ((char *) &offset)[0]; -} - -/* wierd swapping for different-endian u2's, same-endian u4's */ - -PRIVATE void u4c4_s0(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[1]; - buf[1] = ((char *) &offset)[0]; - buf[2] = ((char *) &offset)[3]; - buf[3] = ((char *) &offset)[2]; -} - -/* very wierd swapping for same-endian u2's, different-endian u4's */ - -PRIVATE void u4c4_0s(buf, offset) -register char *buf; -u4_t offset; +PUBLIC u2_pt c2u2(buf) +char *buf; { - buf[0] = ((char *) &offset)[2]; - buf[1] = ((char *) &offset)[3]; - buf[2] = ((char *) &offset)[0]; - buf[3] = ((char *) &offset)[1]; -} - -/* === entry points === */ + u2_pt res; +#ifdef __AS386_16__ + if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ +#endif -PUBLIC void u2c2(buf, offset) -register char *buf; -u2_pt offset; -{ - (*pu2c2) (buf, offset); + res = ((unsigned char *)buf) [int_off[0]] + + ((((unsigned char *)buf) [int_off[1]]) << 8); + return res; } -PUBLIC void u4c4(buf, offset) -register char *buf; -u4_t offset; +PUBLIC u4_t c4u4(buf) +char *buf; { - (*pu4c4) (buf, offset); + u4_t res; + int i; +#ifdef __AS386_16__ + if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */ +#endif + res = 0; + for(i=3; i>=0; i--) + { + res = (res<<8) + ((unsigned char *)buf) [long_off[i]]; + } + return res; } -PUBLIC void u2cn(buf, offset, count) -register char *buf; -u2_pt offset; +PUBLIC u4_t cnu4(buf, count) +char *buf; unsigned count; { switch (count) { case 1: - buf[0] = (char) offset; - return; + return buf[0] & 0xFF; case 2: - (*pu2c2) (buf, offset); - return; + return c2u2(buf); case 4: - (*pu4c4) (buf, (u4_t) offset); - return; + return c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); + return 0; } } -PUBLIC void u4cn(buf, offset, count) -register char *buf; -u4_t offset; +PUBLIC u2_pt cnu2(buf, count) +char *buf; unsigned count; { switch (count) { case 1: - buf[0] = (char) offset; - return; + return buf[0] & 0xFF; case 2: - (*pu2c2) (buf, (u2_pt) (u2_t) offset); - return; + return c2u2(buf); case 4: - (*pu4c4) (buf, offset); - return; - } -} - -/* initialise type conversion, return FALSE if it cannot be handled */ - -PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) -bool_pt big_endian; -bool_pt long_big_endian; -{ - u2_pt conv2; - u4_pt conv4; - char *conv2ptr; - char *conv4ptr; - - if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) - /* dumb preprocessor's don't accept sizeof in #if expressions */ - return FALSE; - - if (big_endian) - { - conv2ptr = (conv4ptr = "\1\2\3\4") + 2; - if (!long_big_endian) - conv4ptr = "\3\4\1\2"; - } - else - { - conv2ptr = conv4ptr = "\4\3\2\1"; - if (long_big_endian) - conv4ptr = "\2\1\4\3"; - } - conv2 = c2u2_00(conv2ptr); - conv4 = c4u4_00(conv4ptr); - if (conv2 == 0x0304) - { - pc2u2 = c2u2_00; - pc4u4 = c4u4_00; - pu2c2 = u2c2_00; - pu4c4 = u4c4_00; - if (conv4 == 0x03040102L) - { - pc4u4 = c4u4_0s; - pu4c4 = u4c4_0s; - } - else if (conv4 != 0x01020304L) - return FALSE; - } - else if (conv2 == 0x0403) - { - pc2u2 = c2u2_ss; - pc4u4 = c4u4_ss; - pu2c2 = u2c2_ss; - pu4c4 = u4c4_ss; - if (conv4 == 0x02010403L) - { - pc4u4 = c4u4_s0; - pu4c4 = u4c4_s0; - } - else if (conv4 != 0x04030201L) - return FALSE; + return (u2_pt) c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); + return 0; } - else - return FALSE; - return TRUE; } - -#ifdef DEBUG_TYPECONV - -main() -{ - char *source; - char target[4]; - u2_t u2; - u2_t u2a; - u4_t u4; - u4_t u4a; - - printf("%u\n", typeconv_init(FALSE, FALSE)); - printf("%u\n", typeconv_init(FALSE, TRUE)); - printf("%u\n", typeconv_init(TRUE, FALSE)); - printf("%u\n", typeconv_init(TRUE, TRUE)); - - typeconv_init(FALSE, FALSE); - source = "\4\3\2\1"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source, 2); - u2cn(target, u2, 2); - if (strncmp(source, target, 2)) - printf("oops9\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source, 2); - u4cn(target, u4a, 2); - if (strncmp(source, target, 2)) - printf("oops10\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\4\3\0\0", 4)) - printf("oops11\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops12\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(FALSE, TRUE); - source = "\2\1\4\3"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source + 2, 2); - u2cn(target, u2, 2); - if (strncmp(source + 2, target, 2)) - printf("oops13\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source + 2, 2); - u4cn(target, u4a, 2); - if (strncmp(source + 2, target, 2)) - printf("oops14\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\0\0\4\3", 4)) - printf("oops15\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops16\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(TRUE, FALSE); - source = "\3\4\1\2"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source, 2); - u2cn(target, u2, 2); - if (strncmp(source, target, 2)) - printf("oops5\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source, 2); - u4cn(target, u4a, 2); - if (strncmp(source, target, 2)) - printf("oops6\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\3\4\0\0", 4)) - printf("oops7\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops8\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(TRUE, TRUE); - source = "\1\2\3\4"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source + 2, 2); - u2cn(target, u2, 2); - if (strncmp(source + 2, target, 2)) - printf("oops1\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source + 2, 2); - u4cn(target, u4a, 2); - if (strncmp(source + 2, target, 2)) - printf("oops2\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\0\0\3\4", 4)) - printf("oops3\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops4\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); -} - -#endif /* DEBUG_TYPECONV */ diff --git a/as/typeconv.c.old b/as/typeconv.c.old new file mode 100644 index 0000000..c51b991 --- /dev/null +++ b/as/typeconv.c.old @@ -0,0 +1,537 @@ +/* typeconv.c - convert between char arrays and unsigneds */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* + c2u2(): 2 byte array to 2 byte unsigned + c4u4(): 4 byte array to 4 byte unsigned + cnu2(): n byte array to 2 byte unsigned + cnu4(): n byte array to 4 byte unsigned + u2c2(): 2 byte unsigned to 2 byte array + u2cn(): 2 byte unsigned to n byte array + u4c4(): 4 byte unsigned to 4 byte array + u4cn(): 4 byte unsigned to n byte array + typeconv_init: (re)initialise for given byte order. + Default is no swapping, but the initialisation should be done + anyway to provide some validity checks (returns FALSE if error). + + Not provided: + c2u4(), c4u2(), u2c4(), u4c2(). + Each of these is best done by truncating or extending a return value + or argument to the appropiate fixed-count function. + c4u2() has too many cases to do in-line conveniently, and the others + are hardly more efficient when done in-line. + + 4 byte orderings for both char arrays and unsigneds are supported: + 0123 - little-endian + 3210 - big-endian + 2301 - little-endian with long words big-endian (pdp11) + 1032 - big-endian with long words little_endian (who knows?) + + The unsigned's byte order is that of the machine on which these + routines are running. + It is determined at run time initialisation since the compiler/ + preprocessor is too dumb to tell us at compile time. +*/ + +#include "syshead.h" +#include "const.h" +#include "type.h" +#include "globvar.h" + +FORWARD u2_pt c2u2_00 P((char *buf)); +FORWARD u4_pt c4u4_00 P((char *buf)); +FORWARD u2_pt c2u2_ss P((char *buf)); +FORWARD u4_pt c4u4_ss P((char *buf)); +FORWARD u4_pt c4u4_s0 P((char *buf)); +FORWARD u4_pt c4u4_0s P((char *buf)); +FORWARD void u2c2_00 P((char *buf, u2_pt offset)); +FORWARD void u4c4_00 P((char *buf, u4_t offset)); +FORWARD void u2c2_ss P((char *buf, u2_pt offset)); +FORWARD void u4c4_ss P((char *buf, u4_t offset)); +FORWARD void u4c4_s0 P((char *buf, u4_t offset)); +FORWARD void u4c4_0s P((char *buf, u4_t offset)); + +PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; +PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; +PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; +PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; + +/* === char arrays to unsigneds === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE u2_pt c2u2_00(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + return offset; +} + +PRIVATE u4_pt c4u4_00(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + ((char *) &offset)[2] = buf[2]; + ((char *) &offset)[3] = buf[3]; + return offset; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE u2_pt c2u2_ss(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + return offset; +} + +PRIVATE u4_pt c4u4_ss(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[3]; + ((char *) &offset)[1] = buf[2]; + ((char *) &offset)[2] = buf[1]; + ((char *) &offset)[3] = buf[0]; + return offset; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE u4_pt c4u4_s0(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + ((char *) &offset)[2] = buf[3]; + ((char *) &offset)[3] = buf[2]; + return offset; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE u4_pt c4u4_0s(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[2]; + ((char *) &offset)[1] = buf[3]; + ((char *) &offset)[2] = buf[0]; + ((char *) &offset)[3] = buf[1]; + return offset; +} + +/* === entry points === */ + +PUBLIC u2_pt c2u2(buf) +char *buf; +{ + return (*pc2u2) (buf); +} + +PUBLIC u4_t c4u4(buf) +char *buf; +{ + return (*pc4u4) (buf); +} + +PUBLIC u2_pt cnu2(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (u2_pt) (*pc4u4) (buf); + default: + return 0; + } +} + +PUBLIC u4_t cnu4(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (*pc4u4) (buf); + default: + return 0; + } +} + +/* === unsigneds to char arrays === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE void u2c2_00(buf, offset) +register char *buf; +u2_pt offset; +{ + + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; +} + +PRIVATE void u4c4_00(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; + buf[2] = ((char *) &offset)[2]; + buf[3] = ((char *) &offset)[3]; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE void u2c2_ss(buf, offset) +register char *buf; +u2_pt offset; +{ + u2_t offset2; + + offset2 = offset; + buf[0] = ((char *) &offset2)[1]; + buf[1] = ((char *) &offset2)[0]; +} + +PRIVATE void u4c4_ss(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[3]; + buf[1] = ((char *) &offset)[2]; + buf[2] = ((char *) &offset)[1]; + buf[3] = ((char *) &offset)[0]; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE void u4c4_s0(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[1]; + buf[1] = ((char *) &offset)[0]; + buf[2] = ((char *) &offset)[3]; + buf[3] = ((char *) &offset)[2]; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE void u4c4_0s(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[2]; + buf[1] = ((char *) &offset)[3]; + buf[2] = ((char *) &offset)[0]; + buf[3] = ((char *) &offset)[1]; +} + +/* === entry points === */ + +PUBLIC void u2c2(buf, offset) +register char *buf; +u2_pt offset; +{ + (*pu2c2) (buf, offset); +} + +PUBLIC void u4c4(buf, offset) +register char *buf; +u4_t offset; +{ + (*pu4c4) (buf, offset); +} + +PUBLIC void u2cn(buf, offset, count) +register char *buf; +u2_pt offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, offset); + return; + case 4: + (*pu4c4) (buf, (u4_t) offset); + return; + } +} + +PUBLIC void u4cn(buf, offset, count) +register char *buf; +u4_t offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, (u2_pt) (u2_t) offset); + return; + case 4: + (*pu4c4) (buf, offset); + return; + } +} + +/* initialise type conversion, return FALSE if it cannot be handled */ + +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; +{ + u2_pt conv2; + u4_pt conv4; + char *conv2ptr; + char *conv4ptr; + + if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) + /* dumb preprocessor's don't accept sizeof in #if expressions */ + return FALSE; + + if (big_endian) + { + conv2ptr = (conv4ptr = "\1\2\3\4") + 2; + if (!long_big_endian) + conv4ptr = "\3\4\1\2"; + } + else + { + conv2ptr = conv4ptr = "\4\3\2\1"; + if (long_big_endian) + conv4ptr = "\2\1\4\3"; + } + conv2 = c2u2_00(conv2ptr); + conv4 = c4u4_00(conv4ptr); + if (conv2 == 0x0304) + { + pc2u2 = c2u2_00; + pc4u4 = c4u4_00; + pu2c2 = u2c2_00; + pu4c4 = u4c4_00; + if (conv4 == 0x03040102L) + { + pc4u4 = c4u4_0s; + pu4c4 = u4c4_0s; + } + else if (conv4 != 0x01020304L) + return FALSE; + } + else if (conv2 == 0x0403) + { + pc2u2 = c2u2_ss; + pc4u4 = c4u4_ss; + pu2c2 = u2c2_ss; + pu4c4 = u4c4_ss; + if (conv4 == 0x02010403L) + { + pc4u4 = c4u4_s0; + pu4c4 = u4c4_s0; + } + else if (conv4 != 0x04030201L) + return FALSE; + } + else + return FALSE; + return TRUE; +} + +#ifdef DEBUG_TYPECONV + +main() +{ + char *source; + char target[4]; + u2_t u2; + u2_t u2a; + u4_t u4; + u4_t u4a; + + printf("%u\n", typeconv_init(FALSE, FALSE)); + printf("%u\n", typeconv_init(FALSE, TRUE)); + printf("%u\n", typeconv_init(TRUE, FALSE)); + printf("%u\n", typeconv_init(TRUE, TRUE)); + + typeconv_init(FALSE, FALSE); + source = "\4\3\2\1"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops9\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops10\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\4\3\0\0", 4)) + printf("oops11\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops12\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(FALSE, TRUE); + source = "\2\1\4\3"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops13\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops14\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\4\3", 4)) + printf("oops15\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops16\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, FALSE); + source = "\3\4\1\2"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops5\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops6\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\3\4\0\0", 4)) + printf("oops7\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops8\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, TRUE); + source = "\1\2\3\4"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops1\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops2\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\3\4", 4)) + printf("oops3\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops4\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); +} + +#endif /* DEBUG_TYPECONV */ |