Keil Logo

CX51: 'far' Function Pointers for Philips MX


Information in this article applies to:

  • Cx51 Version 7 or higher

QUESTION

How do I create a function table with 24-bit function pointers on the Philips MX architecture?

The following code generates only 16-bit function pointers:

#define abs_fct1  0x901000
#define abs_fct2  0x902000

code void (code *fp_tab[]) (void) = { abs_fct1, abs_fct2 };

When I compile this code I get:

*** WARNING C196: mspace probably invalid

Is there a way to avoid this warning message?

I also need to generate ECALL instructions to reach this memory location. However, my application is using the ROM(LARGE) model, and I want to avoid using the ROM(HUGE) model. 

Is there a way to get ECALL instructions when using ROM(LARGE)?

ANSWER

To get 3-byte function pointers, you need to use far pointers in your function pointer definition as shown in the following example. It is also possible to omit the 'far' memory type since the compiler then defaults to 3-byte generic pointers which are identical to the 'far' pointers.

#define abs_fct1  ((void far *) 0x901000)
#define abs_fct2  ((void far *) 0x902000)

code void (far *fp_tab[]) (void) = { abs_fct1, abs_fct2 };

void main (void)  {
  fp_tab[0] ();
}

The program code above compiles without warnings and generates correct calls when using the ROM(HUGE) model.

To stay in the ROM(LARGE) model, call the following assembler interface function that generates the ECALL instruction:

PUBLIC _farcall

?PR?_farcall?farcall SEGMENT CODE
RSEG ?PR?_farcall?farcall

ACC  DATA 0E0H

_farcall:   MOV  A,R1
            PUSH ACC
            MOV  A,R2
            PUSH ACC
            MOV  A,R3
            PUSH ACC
            ERET         ; indirect ECALL

            RET
            END

Call the function farcall from your C code as follows:

extern void _farcall (void far *);

void main (void)  {
  farcall (fp_tab[0]);
}

If you need to call functions that get function parameters, you need to use the following method. The difference is in using a global variable to store the function pointer. This allows parameter passing via different function prototypes that are all using the same entry address in the assembly interface.

PUBLIC _fcall1, _fcall2, farfunc

?DT?_farcall SEGMENT DATA
RSEG ?DT?_farcall
farfunc:    DS   3

?PR?_fcall1?farcall SEGMENT CODE
RSEG ?PR?_fcall1?farcall

_fcall1:
_fcall2:    PUSH farfunc+2
            PUSH farfunc+1
            PUSH farfunc
            ERET         ; indirect ECALL

            RET
            END

Call the function farcall from your C code as follows:

extern void _fcall (int void far *);

extern char *fcall1 (long l1);
extern char *fcall1 (char *p, int i1);
char *p;


void main (void)  {
  farfunc = fp_tab[0];
  p = fcall1 (0x12345678);
  fcall2 (p, 0x8000);
}

MORE INFORMATION

Last Reviewed: Thursday, January 14, 2021


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.