AD sprintf.asm cannot compile

Dear all,

I just found out that the sprintf.asm file distributed by Analog Devices (AD) with their VisualDSP is not even compiling with g21k. Judging from the text it looks like the code was automatically generated.

The code is badly broken, it misses includes and section directives so I don't understand how did it get shipped in the very first place.

Now my biggest problem is, should I write my own sprintf function or should I fix the one broken? I can in principle write it in C instead of assembler (not sure how much will be the difference, though).

Is there anyone out there who ever needed a sprintf while using the ADSP21K targets? Any suggestions?

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Reply to
Alessandro Basili
Loading thread data ...

The VisualDSP compiler and G21K are not the same. G21K is a GCC derivative, the VDSP compiler is based on the Amsterdam Kit. They are mostly compatible at the C/C++ level, but their assemblers are very different.

Why are you using G21K if you have VisualDSP?

Try using the G21K version.

George

Reply to
George Neuner

Nope never used any of stdio. Why do you need sprintf if I may ask?

Mark DeArman

Reply to
Mac Decman

Alessandro Basili writes:

If you only really need integer output there are public domain C implementations that work fine and are tiny. I use one based originally on public domain code, extended a bit to handle fixed point using various custom format specifiers. (letters representing "Deci", "centi", "milli" etc).

I find it very useful.

/* fmt.h header file for formatted output routines (a cut-down printf implementation) */ #ifndef H_FMT #define H_FMT #ifdef __cplusplus extern "C" { #endif #if 0 } #endif

/* %[flag][width][.prec][mod][conv] flag: - left justify, pad right w/ blanks DONE 0 pad left w/ 0 for numerics DONE + always print sign, + or - no ' ' (blank) no # (???) no

width: (field width) DONE

prec: (precision) no

conv: d,i decimal int DONE u decimal unsigned DONE o octal DONE x,X hex DONE f,e,g,E,G float no c char DONE s string DONE p ptr DONE

mod: N near ptr DONE F far ptr no h short (16-bit) int DONE l long (32-bit) int DONE L long long (64-bit) int no

*****************************************************************************/

#include "stdarg.h" typedef int (*fnptr_t)(unsigned c, void **helper);

int fmt_do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr); int fmt_vsprintf(char *buf, const char *fmt, va_list args); int fmt_sprintf(char *buf, const char *fmt, ...); int fmt_vprintf_help(unsigned c, void **ptr); int fmt_vprintf(const char *fmt, va_list args); int fmt_printf(const char *fmt, ...);

#ifdef __cplusplus } #endif /*__cplusplus */ #endif /*H_FMT */

.......

/***************************************************************************** Stripped-down printf() Chris Giese

formatting link
Release date: Dec 12, 2003 This code is public domain (no copyright). You can do whatever you want with it.

Revised Dec 12, 2003

- fixed vsprintf() and sprintf() in test code

Revised Jan 28, 2002

- changes to make characters 0x80-0xFF display properly

Revised June 10, 2001

- changes to make vsprintf() terminate string with '\0'

Revised May 12, 2000

- math in DO_NUM is now unsigned, as it should be

- %0 flag (pad left with zeroes) now works

- actually did some TESTING, maybe fixed some other bugs

%[flag][width][.prec][mod][conv] flag: - left justify, pad right w/ blanks DONE 0 pad left w/ 0 for numerics DONE + always print sign, + or - no ' ' (blank) no # (???) no

width: (field width) DONE

prec: (precision) no

conv: d,i decimal int DONE u decimal unsigned DONE o octal DONE x,X hex DONE f,e,g,E,G float no c char DONE s string DONE p ptr DONE

mod: N near ptr DONE F far ptr no h short (16-bit) int DONE l long (32-bit) int DONE L long long (64-bit) int no

*****************************************************************************/ #include /* strlen() */ //#include /* stdout, putchar(), fputs() (but not printf() :) */ #include "stdarg.h"

/* flags used in processing format string */ #define PR_LJ 0x01 /* left justify */ #define PR_CA 0x02 /* use A-F instead of a-f for hex */ #define PR_SG 0x04 /* signed numeric conversion (%d vs. %u) */ #define PR_32 0x08 /* long (32-bit) numeric conversion */ #define PR_16 0x10 /* short (16-bit) numeric conversion */ #define PR_WS 0x20 /* PR_SG set and num was < 0 */ #define PR_LZ 0x40 /* pad left with '0' instead of ' ' */ #define PR_FP 0x80 /* pointers are far */ #define PR_FX 0x100 /* fixed point number */ /* largest number handled is 2^32-1, lowest radix handled is 8. 2^32-1 in base 8 has 11 digits (add 5 for trailing NUL and for slop) */ #define PR_BUFLEN 16

typedef int (*fnptr_t)(unsigned c, void **helper); /***************************************************************************** name: do_printf action: minimal subfunction for ?printf, calls function 'fn' with arg 'ptr' for each character to be output returns:total number of characters output

*****************************************************************************/ int fmt_do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr) { unsigned flags, actual_wd, count, given_wd; char *where, buf[PR_BUFLEN]; unsigned char state, radix; long num; int precision_display, precision_encode; state = flags = count = given_wd = precision_display = precision_encode = 0; /* begin scanning format specifier list */ for(; *fmt; fmt++) { switch(state) { /* STATE 0: AWAITING % */ case 0: if(*fmt != '%') /* not %... */ { fn(*fmt, &ptr); /* ...just echo it */ count++; break; } /* found %, get next char and advance state to check if next char is a flag */ state++; fmt++; /* FALL THROUGH */ /* STATE 1: AWAITING FLAGS (%-0) */ case 1: if(*fmt == '%') /* %% */ { fn(*fmt, &ptr); count++; state = flags = given_wd = 0; break; } if(*fmt == '-') { if(flags & PR_LJ)/* %-- is illegal */ state = flags = given_wd = 0; else flags |= PR_LJ; break; } /* not a flag char: advance state to check if it's field width */ state++; /* check now for '%0...' */ if(*fmt == '0') { flags |= PR_LZ; fmt++; } /* FALL THROUGH */ /* STATE 2: AWAITING (NUMERIC) FIELD WIDTH */ case 2: if(*fmt >= '0' && *fmt 0) { num *= ((int []){0,10,100,1000,10000,100000,1000000})[pow]; } } /* convert binary to octal/decimal/hex ASCII OK, I found my mistake. The math here is _always_ unsigned */ int digit_counter = 0; do { if(flags & PR_FX && digit_counter == precision_display) { *--where = '.'; } unsigned long temp; temp = (unsigned long)num % radix; where--; if(temp < 10) *where = temp + '0'; else if(flags & PR_CA) *where = temp - 10 + 'A'; else *where = temp - 10 + 'a'; num = (unsigned long)num / radix; digit_counter++; } while(num != 0 || ((flags & PR_FX) && digit_counter actual_wd) { fn(flags & PR_LZ ? '0' : ' ', &ptr); count++; given_wd--; } } /* if we pad left with SPACES, do the sign now */ if((flags & (PR_WS | PR_LZ)) == PR_WS) { fn('-', &ptr); count++; } /* emit string/char/converted number */ while(*where != '\0') { fn(*where++, &ptr); count++; } /* pad on right with spaces (for left justify) */ if(given_wd < actual_wd) given_wd = 0; else given_wd -= actual_wd; for(; given_wd; given_wd--) { fn(' ', &ptr); count++; } break; default: break; } default: state = flags = given_wd = 0; break; } } return count; }

/***************************************************************************** SPRINTF

*****************************************************************************/ static int vsprintf_help(unsigned c, void **ptr) { char *dst; dst = *ptr; *dst++ = (char)c; *ptr = dst; return 0 ; } /***************************************************************************** *****************************************************************************/ int fmt_vsprintf(char *buf, const char *fmt, va_list args) { int rv; rv = fmt_do_printf(fmt, args, vsprintf_help, (void *)buf); buf[rv] = '\0'; return rv; } /***************************************************************************** *****************************************************************************/ int fmt_sprintf(char *buf, const char *fmt, ...) { va_list args; int rv; va_start(args, fmt); rv = fmt_vsprintf(buf, fmt, args); va_end(args); return rv; } /***************************************************************************** PRINTF You must write your own putchar() *****************************************************************************/ int fmt_vprintf_help(unsigned c, void **ptr) { // putchar(c); return 0 ; } /***************************************************************************** *****************************************************************************/ int fmt_vprintf(const char *fmt, va_list args) { return fmt_do_printf(fmt, args, fmt_vprintf_help, NULL); } /***************************************************************************** *****************************************************************************/ int fmt_printf(const char *fmt, ...) { va_list args; int rv;

va_start(args, fmt); rv = fmt_vprintf(fmt, args); va_end(args); return rv; }

--

John Devereux
Reply to
John Devereux

My bad, indeed the C runtime library I was compiling with g21k *is* the one delivered with g21k. I had also the archived library (libc.a), but I am working in a GNU/Linux environment and had to rebuild everything from scratch since the librarian lib21k is not available and the /ar/ from binutils is not supporting COFF format (if you are interested there's another post discussing this subject ).

Reply to
alb

Actually after some talking I also started to ask myself the same question. The main idea behind was to have a debug tool to print some characters in the output data, but then I guess it would be much easier to encode the information I want in a suitable format that I can decode later on when processing the output data.

Part of the debug functions were copied from another embedded project which was on an 8051 and the library did support it. I think I rushed in too quickly asking for an sprintf function before even realizing that I maybe don't need one.

I will try to think harder next time before posting... (even though I think I did...)

Reply to
alb

Unix/Linix static linking libraries are in a.out (assembler output) format, not in COFF (or ELF, DWARF, PE, etc.). The ar utility does not support any of these linker executable formats.

George

Reply to
George Neuner

But g21k (with its binutils) is a cross-compiler, so AIUI its output format is unrelated to the host native conventions.

When I used g21k about a decade ago, it generated COFF, and I believe g21k has not been maintained or updated extensively since that time.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .
Reply to
Niklas Holsti

Excuse me - The archive contains relocatable binary files in the native format of the development utilities, e.g. ELF.

a.out does not support enough information to be properly linked to COFF or ELF. The current native format for Linux is ELF.

--

Tauno Voipio
Reply to
Tauno Voipio

True enough, but G21K is a GCC derivative - the assembler produces and the library utility operates on a.out format object files.

The *linker* produces COFF executables, but the libraries are not in COFF format.

When I used G21K - also a while ago on 2106x - the linker stripped symbol information and produced absolute addressed load segments that were packaged into simplified COFF executable format sans symbol or string information. I guess AD figured no one needed it. I haven't used G21K since it became a Google project so I don't know if that still is the case.

VDSP 4.x (the last I used) produced ELF executables with symbol and optional debug information, but VDSP also included a chip simulator/debugger that could use the information.

George

Reply to
George Neuner

I dug out some of my g21k-compiled files from last century (1999, to be exact). As I remember, but I'm not sure, these were compiled with g21k on a Solaris SPARC workstation. Here is what the "file" command reports for them:

vecdemo.c: ASCII Pascal program text, with CRLF line terminators vecdemo.exe: COFF DSP21k executable, not stripped vecdemo.o: COFF DSP21k relocatable object, not stripped

So the compiler/assembler output, vecdemo.o, is in COFF, as is the linker output vecdemo.exe. Libraries created with "ar" would also contain COFF, then. But perhaps other versions of g21k use other formats.

Yes, I also remember that the symbol-info in the executables was very poor. Especially the poor mapping between source lines and code addresses was a problem. But there was some symbol-info, at least function names and their entry addresses, as I recall.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .
Reply to
Niklas Holsti

Sorry, I goofed in writing Unix/Linux. We are talking about an older version of GCC that doesn't use ELF.

George

Reply to
George Neuner

No offense intended.

The binary format(s) is determined by the binary utilities (binutils, as, ld, and friends) and the binary format library (BFD) which is used by the utilities.

The compiler needs some basic support by the binary format, which detemines the minimum support from needed binutils.

--

regards, Tauno
Reply to
Tauno Voipio

Well I have seen projects where they either utilized the VisualDSP background telemetry channel or setup a UART for debugging during run time.

I was just wondering since in my project I run all of the non-signal processing functions on an SiLabs 8051. After some profiling it was painfully obvious I was not getting the bang for my buck by running any of the enduser logic directly on the DSP.

Mark DeArman

Reply to
Mac Decman

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.