/******************************************************************************
far_ptr.h

Author R32151

Support for manipulating 23-bit 'wide' pointers parts at a C level.
******************************************************************************/

                           /*prevent duplicated includes */
#ifndef FAR_PTR_H       
#define FAR_PTR_H

/******************************************************************************
Union to contain a 23-bit 'wide' pointer to allow access to component page and 
local address. 
******************************************************************************/
typedef union 
{
   void *__far  fptr;     /* GPAGE global pointer */ 
   void *__rptr rptr; 	  /* RPAGE ram pointer */
   void *__eptr eptr; 	  /* EEPAGE eeprom pointer */
   void *__pptr pptr; 	  /* PPAGE flash pointer */
   struct 
   {
      unsigned char page;			  /* 7-bit page address part of 23-bit pointer */
      unsigned int  addr;			  /* 16-bit local address part of 23-bit pointer */
   } part;
} t__wptr;

/******************************************************************************
Macros to access component page and local address of 23-bit 'wide' pointer 
parts at a C level. 
******************************************************************************/
#define WP_PAGE(w_ptr0) (((t__wptr*)(&w_ptr0))->part.page)	 
#define WP_ADDR(w_ptr0) (((t__wptr*)(&w_ptr0))->part.addr)	 


/******************************************************************************
Macros to add and subtract (long) values from 23-bit far pointer.
This approach does not work with rptr, eptr & pprt types. In the case that 
any data accessed by a pointer can cross a page boundary ALWAYS use 
a far pointer if pointer maths is required. 
******************************************************************************/
#define FP_ADD(f_ptr, f_delta)  WP_PAGE(f_ptr)=(((((unsigned long int)WP_PAGE(f_ptr))<<16)|((unsigned long int)WP_ADDR(f_ptr)))+ f_delta)>>16; \
                                WP_ADDR(f_ptr)=(((unsigned long int)WP_ADDR(f_ptr))+ f_delta)&0xffff;

#define FP_SUB(f_ptr, f_delta)  WP_PAGE(f_ptr)=(((((unsigned long int)WP_PAGE(f_ptr))<<16)|((unsigned long int)WP_ADDR(f_ptr)))- f_delta)>>16; \
                                WP_ADDR(f_ptr)=(((unsigned long int)WP_ADDR(f_ptr))- f_delta)&0xffff;
                                
#endif /* FAR_PTR_H */