I would dearly love to replace some of the Keil library functions that are used by intrinsics, such as ?C?COPY, which is called by memcpy (and by other things). My current goal is to generate runtime errors on certain types of copies, but replacement would be useful for other purposes. I've actually written my own implementation of ?C?COPY, which works fine. The inline instructions are still emitted by the compiler and my version is linked. However, I'm concerned about compatibility with future compiler releases. I'm supposing that the interface can't change, because this would break older libraries, which could be third party. But other library functionality may depend on something internal to the Keil ?C?COPY implementation, or may do so in future. For my current purposes, I'm thinking of patching the entry to the Keil ?C?COPY after the code is built, to call my checking routine. This only requires that the interface doesn't change. Has anyone else tried anything like this? Any comments on my assumption that the interface can't change? PS - I know I can acheive my ends by writing my own memcpy and redefining memcpy() with a macro, but then heaps more code will be generated, because the calls will be far less efficient, without the special parameter passing.
I remember experimenting with this. It is possible to generate your own version of ?C?COPY, but this was all some time ago and I cannot get at my results just now. The most obvious reason for wanting to do this is to have a much more compact code: the standard library version of ?C?COPY is quite large, more than 1k bytes if I remember correctly. Therefore, memcpy() and its string.h library siblings can each swallow up a sizeable chunk of ROM. For small ROM size projects, it really would be helful if Keil had a build option to include a compact, but slow version of the string.h library - including ?C?COPY. That really should not be too difficult to do. ?C?COPY can get included in a build even when you don't explicitly use memcpy() because it is used to, for example, copy a structure variable. That is the case even when a structure is very small (no larger than a long int), it is even called to copy a one byte structure when that structure contains bit fields. It would be nice if C51 could do something about this. I recall jumping through hoops to avoid ?C?COPY being incorported into a build. For example, copying a structure field-by-field - which can avoid a ?C?COPY call and can be much faster. If I recall correctly, it was also possible to avoid ?C?COPY for small structures by using casting or unions. From your posting it sound like you are trying to do something slightly more sophisticated: a version of ?C?COPY that only deals with a subset of the possible memory types and emits a runtime error if you invoke it with a memory type it cannot deal with. That sounds like a really good idea too. The interface to ?C?COPY has been stable for as long as I can remember, but as with any compiler there is no garantee. It is a pity that the special case for passing parameters was not made explicilty normal for any function call where the first two parameters are generic pointers - but I guess it is too late to change that.
Thanks for you comments. I agree that it would be useful for Keil to open the interface to ?C?COPY et. al., so that custom versions may be implemented. It is rather a lot of code, much of which is guaranteed not to be used in most applications. Additionally, faster implementations are possible on some processors, and some hardware architectures may permit shortcuts.
Wow! I replaced ?C?COPY, ?C?MOVE and ?C?MEMSET, implementing only the cases I need and saved approx 256 bytes. I could actually get quite a bit more back, but I kept the code fairly similar to the Keil versions in case I need to reimplement some of it. I completely disassembled the library code and the only worrying things I found were - There seems to be a redundant instruction in ?C?COPY, which hints at a separate entry point. I kept the replacement code logically consistent with this possibility. The PDATA<->XDATA memmove cases do not cater for overlap, though this is possible, at least in hardware terms. Maybe the compiler prevents this? The CODE->XDATA case caters for overlap. This must be possible on some architectures, though certainly not in our case.
saved approx 256 bytes. great, now for the full story: what happened to execution time? Erik
Identical - I just removed the cases that I don't use - like PDATA<->XDATA copies etc. And looking at the code, I could slightly increase the execution speed using less space if I wanted to.