| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970 |
- /******************************************************************************
- FILE : datapage.c
- PURPOSE : paged data access runtime routines
- MACHINE : Freescale 68HC12 (Target)
- LANGUAGE : ANSI-C
- HISTORY : 21.7.96 first version created
- ******************************************************************************/
- #include "hidef.h"
- #include "non_bank.sgm"
- #include "runtime.sgm"
- #ifndef __HCS12X__ /* it's different for the HCS12X. See the text below at the #else // __HCS12X__ */
- /*
- According to the -Cp option of the compiler the
- __DPAGE__, __PPAGE__ and __EPAGE__ macros are defined.
- If none of them is given as argument, then no page accesses should occur and
- this runtime routine should not be used !
- To be on the save side, the runtime routines are created anyway.
- If some of the -Cp options are given an adapted versions which only covers the
- needed cases is produced.
- */
- /* if no compiler option -Cp is given, it is assumed that all possible are given : */
- /* Compile with option -DHCS12 to activate this code */
- #if defined(HCS12) || defined(_HCS12) || defined(__HCS12__) /* HCS12 family has PPAGE register only at 0x30 */
- #define PPAGE_ADDR (0x30+REGISTER_BASE)
- #ifndef __PPAGE__ /* may be set already by option -CPPPAGE */
- #define __PPAGE__
- #endif
- /* Compile with option -DDG128 to activate this code */
- #elif defined DG128 /* HC912DG128 derivative has PPAGE register only at 0xFF */
- #define PPAGE_ADDR (0xFF+REGISTER_BASE)
- #ifndef __PPAGE__ /* may be set already by option -CPPPAGE */
- #define __PPAGE__
- #endif
- #elif defined(HC812A4)
- /* all setting default to A4 already */
- #endif
- #if !defined(__EPAGE__) && !defined(__PPAGE__) && !defined(__DPAGE__)
- /* as default use all page registers */
- #define __DPAGE__
- #define __EPAGE__
- #define __PPAGE__
- #endif
- /* modify the following defines to your memory configuration */
- #define EPAGE_LOW_BOUND 0x400u
- #define EPAGE_HIGH_BOUND 0x7ffu
- #define DPAGE_LOW_BOUND 0x7000u
- #define DPAGE_HIGH_BOUND 0x7fffu
- #define PPAGE_LOW_BOUND (DPAGE_HIGH_BOUND+1)
- #define PPAGE_HIGH_BOUND 0xBFFFu
- #define REGISTER_BASE 0x0u
- #ifndef DPAGE_ADDR
- #define DPAGE_ADDR (0x34u+REGISTER_BASE)
- #endif
- #ifndef EPAGE_ADDR
- #define EPAGE_ADDR (0x36u+REGISTER_BASE)
- #endif
- #ifndef PPAGE_ADDR
- #define PPAGE_ADDR (0x35u+REGISTER_BASE)
- #endif
- /*
- The following parts about the defines are assumed in the code of _GET_PAGE_REG :
- - the memory region controlled by DPAGE is above the area controlled by the EPAGE and
- below the area controlled by the PPAGE.
- - the lower bound of the PPAGE area is equal to be the higher bound of the DPAGE area + 1
- */
- #if EPAGE_LOW_BOUND >= EPAGE_HIGH_BOUND || EPAGE_HIGH_BOUND >= DPAGE_LOW_BOUND || DPAGE_LOW_BOUND >= DPAGE_HIGH_BOUND || DPAGE_HIGH_BOUND >= PPAGE_LOW_BOUND || PPAGE_LOW_BOUND >= PPAGE_HIGH_BOUND
- #error /* please adapt _GET_PAGE_REG for this non default page configuration */
- #endif
- #if DPAGE_HIGH_BOUND+1 != PPAGE_LOW_BOUND
- #error /* please adapt _GET_PAGE_REG for this non default page configuration */
- #endif
- /* this module does either control if any access is in the bounds of the specified page or */
- /* ,if only one page is specified, just use this page. */
- /* This behavior is controlled by the define USE_SEVERAL_PAGES. */
- /* If !USE_SEVERAL_PAGES does increase the performance significantly */
- /* NOTE : When !USE_SEVERAL_PAGES, the page is also set for accesses outside of the area controlled */
- /* by this single page. But this is should not cause problems because the page is restored to the old value before any other access could occur */
- #if !defined(__DPAGE__) && !defined(__EPAGE__) && !defined(__PPAGE__)
- /* no page at all is specified */
- /* only specifying the right pages will speed up these functions a lot */
- #define USE_SEVERAL_PAGES 1
- #elif defined(__DPAGE__) && defined(__EPAGE__) || defined(__DPAGE__) && defined(__PPAGE__) || defined(__EPAGE__) && defined(__PPAGE__)
- /* more than one page register is used */
- #define USE_SEVERAL_PAGES 1
- #else
- #define USE_SEVERAL_PAGES 0
- #if defined(__DPAGE__) /* check which pages are used */
- #define PAGE_ADDR PPAGE_ADDR
- #elif defined(__EPAGE__)
- #define PAGE_ADDR EPAGE_ADDR
- #elif defined(__PPAGE__)
- #define PAGE_ADDR PPAGE_ADDR
- #else /* we do not know which page, decide it at runtime */
- #error /* must not happen */
- #endif
- #endif
- #if USE_SEVERAL_PAGES /* only needed for several pages support */
- /*--------------------------- _GET_PAGE_REG --------------------------------
- Runtime routine to detect the right register depending on the 16 bit offset part
- of an address.
- This function is only used by the functions below.
- Depending on the compiler options -Cp different versions of _GET_PAGE_REG are produced.
- Arguments :
- - Y : offset part of an address
- Result :
- if address Y is controlled by a page register :
- - X : address of page register if Y is controlled by an page register
- - Zero flag cleared
- - all other registers remain unchanged
- if address Y is not controlled by a page register :
- - Zero flag is set
- - all registers remain unchanged
- --------------------------- _GET_PAGE_REG ----------------------------------*/
- #if defined(__DPAGE__)
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
- __asm {
- L_DPAGE:
- CPY #DPAGE_LOW_BOUND ;// test of lower bound of DPAGE
- #if defined(__EPAGE__)
- BLO L_EPAGE ;// EPAGE accesses are possible
- #else
- BLO L_NOPAGE ;// no paged memory below accesses
- #endif
- CPY #DPAGE_HIGH_BOUND ;// test of higher bound DPAGE/lower bound PPAGE
- #if defined(__PPAGE__)
- BHI L_PPAGE ;// EPAGE accesses are possible
- #else
- BHI L_NOPAGE ;// no paged memory above accesses
- #endif
- FOUND_DPAGE:
- LDX #DPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- #if defined(__PPAGE__)
- L_PPAGE:
- CPY #PPAGE_HIGH_BOUND ;// test of higher bound of PPAGE
- BHI L_NOPAGE
- FOUND_PPAGE:
- LDX #PPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- #endif
- #if defined(__EPAGE__)
- L_EPAGE:
- CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
- BLO L_NOPAGE
- CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
- BHI L_NOPAGE
- FOUND_EPAGE:
- LDX #EPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- #endif
- L_NOPAGE:
- ORCC #0x04 ;// sets zero flag
- RTS
- }
- }
- #else /* !defined(__DPAGE__) */
- #if defined( __PPAGE__ )
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
- __asm {
- L_PPAGE:
- CPY #PPAGE_LOW_BOUND ;// test of lower bound of PPAGE
- #if defined( __EPAGE__ )
- BLO L_EPAGE
- #else
- BLO L_NOPAGE ;// no paged memory below
- #endif
- CPY #PPAGE_HIGH_BOUND ;// test of higher bound PPAGE
- BHI L_NOPAGE
- FOUND_PPAGE:
- LDX #PPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- #if defined( __EPAGE__ )
- L_EPAGE:
- CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
- BLO L_NOPAGE
- CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
- BHI L_NOPAGE
- FOUND_EPAGE:
- LDX #EPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- #endif
- L_NOPAGE: ;// not in any allowed page area
- ;// its a far access to a non paged variable
- ORCC #0x04 ;// sets zero flag
- RTS
- }
- }
- #else /* !defined(__DPAGE__ ) && !defined( __PPAGE__) */
- #if defined(__EPAGE__)
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
- __asm {
- L_EPAGE:
- CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
- BLO L_NOPAGE
- CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
- BHI L_NOPAGE
- FOUND_EPAGE:
- LDX #EPAGE_ADDR ;// load page register address and clear zero flag
- RTS
- L_NOPAGE: ;// not in any allowed page area
- ;// its a far access to a non paged variable
- ORCC #0x04 ;// sets zero flag
- RTS
- }
- }
- #endif /* defined(__EPAGE__) */
- #endif /* defined(__PPAGE__) */
- #endif /* defined(__DPAGE__) */
- #endif /* USE_SEVERAL_PAGES */
- /*--------------------------- _SET_PAGE --------------------------------
- Runtime routine to set the right page register. This routine is used if the compiler
- does not know the right page register, i.e. if the option -Cp is used for more than
- one page register or if the runtime option is used for one of the -Cp options.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- Result :
- - page part written into the correct page register.
- - the old page register content is destroyed
- - all processor registers remains unchanged
- --------------------------- _SET_PAGE ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _SET_PAGE(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- STAB 0,X ;// set page register
- L_NOPAGE:
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- STAB PAGE_ADDR ;// set page register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _LOAD_FAR_8 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- Result :
- - value to be read in the B register
- - all other registers remains unchanged
- - all page register still contain the same value
- --------------------------- _LOAD_FAR_8 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _LOAD_FAR_8(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHA ;// save A register
- LDAA 0,X ;// save page register
- STAB 0,X ;// set page register
- LDAB 0,Y ;// actual load, overwrites page
- STAA 0,X ;// restore page register
- PULA ;// restore A register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- LDAB 0,Y ;// actual load, overwrites page
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHA ;// save A register
- LDAA PAGE_ADDR ;// save page register
- STAB PAGE_ADDR ;// set page register
- LDAB 0,Y ;// actual load, overwrites page
- STAA PAGE_ADDR ;// restore page register
- PULA ;// restore A register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _LOAD_FAR_16 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- Result :
- - value to be read in the Y register
- - all other registers remains unchanged
- - all page register still contain the same value
- --------------------------- _LOAD_FAR_16 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _LOAD_FAR_16(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHA ;// save A register
- LDAA 0,X ;// save page register
- STAB 0,X ;// set page register
- LDY 0,Y ;// actual load, overwrites address
- STAA 0,X ;// restore page register
- PULA ;// restore A register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- LDY 0,Y ;// actual load, overwrites address
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHA ;// save A register
- LDAA PAGE_ADDR ;// save page register
- STAB PAGE_ADDR ;// set page register
- LDY 0,Y ;// actual load, overwrites address
- STAA PAGE_ADDR ;// restore page register
- PULA ;// restore A register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _LOAD_FAR_24 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- Result :
- - value to be read in the Y:B registers
- - all other registers remains unchanged
- - all page register still contain the same value
- --------------------------- _LOAD_FAR_24 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _LOAD_FAR_24(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHA ;// save A register
- LDAA 0,X ;// save page register
- STAB 0,X ;// set page register
- LDAB 0,Y ;// actual load, overwrites page of address
- LDY 1,Y ;// actual load, overwrites offset of address
- STAA 0,X ;// restore page register
- PULA ;// restore A register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- LDAB 0,Y ;// actual load, overwrites page of address
- LDY 1,Y ;// actual load, overwrites offset of address
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHA ;// save A register
- LDAA PAGE_ADDR ;// save page register
- STAB PAGE_ADDR ;// set page register
- LDAB 0,Y ;// actual load, overwrites page of address
- LDY 1,Y ;// actual load, overwrites offset of address
- STAA PAGE_ADDR ;// restore page register
- PULA ;// restore A register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _LOAD_FAR_32 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- Result :
- - low 16 bit of value to be read in the D registers
- - high 16 bit of value to be read in the Y registers
- - all other registers remains unchanged
- - all page register still contain the same value
- --------------------------- _LOAD_FAR_32 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _LOAD_FAR_32(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- LDAA 0,X ;// save page register
- PSHA ;// put it onto the stack
- STAB 0,X ;// set page register
- LDD 2,Y ;// actual load, low word
- LDY 0,Y ;// actual load, high word
- MOVB 1,SP+,0,X ;// restore page register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- LDD 2,Y ;// actual load, low word
- LDY 0,Y ;// actual load, high word
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- LDAA PAGE_ADDR ;// save page register
- PSHA ;// put it onto the stack
- STAB PAGE_ADDR ;// set page register
- LDD 2,Y ;// actual load, low word
- LDY 0,Y ;// actual load, high word
- MOVB 1,SP+,PAGE_ADDR ;// restore page register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _STORE_FAR_8 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- - value to be stored in the B register
- Result :
- - value stored at the address
- - all registers remains unchanged
- - all page register still contain the same value
- --------------------------- _STORE_FAR_8 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _STORE_FAR_8(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHB ;// save B register
- LDAB 0,X ;// save page register
- MOVB 0,SP, 0,X ;// set page register
- STAA 0,Y ;// store the value passed in A
- STAB 0,X ;// restore page register
- PULB ;// restore B register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- STAA 0,Y ;// store the value passed in A
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHB ;// save A register
- LDAB PAGE_ADDR ;// save page register
- MOVB 0,SP,PAGE_ADDR ;// set page register
- STAA 0,Y ;// store the value passed in A
- STAB PAGE_ADDR ;// restore page register
- PULB ;// restore B register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _STORE_FAR_16 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- - value to be stored in the X register
- Result :
- - value stored at the address
- - all registers remains unchanged
- - all page register still contain the same value
- --------------------------- _STORE_FAR_16 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _STORE_FAR_16(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHA
- LDAA 0,X ;// save page register
- STAB 0,X ;// set page register
- MOVW 1,SP,0,Y ;// store the value passed in X
- STAA 0,X ;// restore page register
- PULA ;// restore A register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- STX 0,Y ;// store the value passed in X
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHA ;// save A register
- LDAA PAGE_ADDR ;// save page register
- STAB PAGE_ADDR ;// set page register
- STX 0,Y ;// store the value passed in X
- STAA PAGE_ADDR ;// restore page register
- PULA ;// restore A register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _STORE_FAR_24 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address in the B register
- - value to be stored in the X:A registers (X : low 16 bit, A : high 8 bit)
- Result :
- - value stored at the address
- - all registers remains unchanged
- - all page register still contain the same value
- --------------------------- _STORE_FAR_24 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _STORE_FAR_24(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHA
- LDAA 0,X ;// save page register
- STAB 0,X ;// set page register
- MOVW 1,SP, 1,Y ;// store the value passed in X
- MOVB 0,SP, 0,Y ;// store the value passed in A
- STAA 0,X ;// restore page register
- PULA ;// restore A register
- PULX ;// restore X register
- RTS
- L_NOPAGE:
- STX 1,Y ;// store the value passed in X
- STAA 0,Y ;// store the value passed in X
- PULX ;// restore X register
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHA ;// save A register
- LDAA PAGE_ADDR ;// save page register
- STAB PAGE_ADDR ;// set page register
- MOVB 0,SP, 0,Y ;// store the value passed in A
- STX 1,Y ;// store the value passed in X
- STAA PAGE_ADDR ;// restore page register
- PULA ;// restore A register
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _STORE_FAR_32 --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of an address in the Y register
- - page part of an address is on the stack at 3,SP (just below the return address)
- - value to be stored in the X:D registers (D : low 16 bit, X : high 16 bit)
- Result :
- - value stored at the address
- - all registers remains unchanged
- - the page part is removed from the stack
- - all page register still contain the same value
- --------------------------- _STORE_FAR_32 ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _STORE_FAR_32(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- PSHX ;// save X register
- __PIC_JSR(_GET_PAGE_REG)
- BEQ L_NOPAGE
- PSHD
- LDAA 0,X ;// save page register
- MOVB 6,SP, 0,X ;// set page register
- MOVW 2,SP, 0,Y ;// store the value passed in X (high word)
- MOVW 0,SP, 2,Y ;// store the value passed in D (low word)
- STAA 0,X ;// restore page register
- PULD ;// restore A register
- BRA done
- L_NOPAGE:
- MOVW 0,SP, 0,Y ;// store the value passed in X (high word)
- STD 2,Y ;// store the value passed in D (low word)
- done:
- PULX ;// restore X register
- MOVW 0,SP, 1,+SP ;// move return address
- RTS
- }
- #else /* USE_SEVERAL_PAGES */
- __asm {
- PSHD ;// save D register
- LDAA PAGE_ADDR ;// save page register
- LDAB 4,SP ;// load page part of address
- STAB PAGE_ADDR ;// set page register
- STX 0,Y ;// store the value passed in X
- MOVW 0,SP, 2,Y ;// store the value passed in D (low word)
- STAA PAGE_ADDR ;// restore page register
- PULD ;// restore D register
- MOVW 0,SP, 1,+SP ;// move return address
- RTS
- }
- #endif /* USE_SEVERAL_PAGES */
- }
- /*--------------------------- _FAR_COPY_RC --------------------------------
- This runtime routine is used to access paged memory via a runtime function.
- It may also be used if the compiler option -Cp is not used with the runtime argument.
- Arguments :
- - offset part of the source int the X register
- - page part of the source in the A register
- - offset part of the dest int the Y register
- - page part of the dest in the B register
- - number of bytes to be copied is defined by the next 2 bytes after the return address.
- Result :
- - memory area copied
- - no registers are saved, i.e. all registers may be destroyed
- - all page register still contain the same value as before the call
- - the function returns after the constant defining the number of bytes to be copied
- stack-structure at the loop-label:
- 0,SP : destination offset
- 2,SP : source page
- 3,SP : destination page
- 4,SP : source offset
- 6,SP : points to length to be copied. This function returns after the size
- A usual call to this function looks like:
- struct Huge src, dest;
- ; ...
- LDX #src
- LDAA #PAGE(src)
- LDY #dest
- LDAB #PAGE(dest)
- JSR _FAR_COPY_RC
- DC.W sizeof(struct Huge)
- ; ...
- --------------------------- _FAR_COPY_RC ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_RC(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- DEX ;// source addr-=1, because loop counter ends at 1
- PSHX ;// save source offset
- PSHD ;// save both pages
- DEY ;// destination addr-=1, because loop counter ends at 1
- PSHY ;// save destination offset
- LDY 6,SP ;// Load Return address
- LDX 2,Y+ ;// Load Size to copy
- STY 6,SP ;// Store adjusted return address
- loop:
- LDD 4,SP ;// load source offset
- LEAY D,X ;// calculate actual source address
- LDAB 2,SP ;// load source page
- __PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
- PSHB ;// save value
- LDD 0+1,SP ;// load destination offset
- LEAY D,X ;// calculate actual destination address
- PULA ;// restore value
- LDAB 3,SP ;// load destination page
- __PIC_JSR(_STORE_FAR_8) ;// store one byte
- DEX
- BNE loop
- LEAS 6,SP ;// release stack
- _SRET ;// debug info only: This is the last instr of a function with a special return
- RTS ;// return
- }
- #else
- __asm {
- PSHD ;// store page registers
- TFR X,D
- PSHY ;// temporary space
- LDY 4,SP ;// load return address
- ADDD 2,Y+ ;// calculate source end address. Increment return address
- STY 4,SP
- PULY
- PSHD ;// store src end address
- LDAB 2,SP ;// reload source page
- LDAA PAGE_ADDR ;// save page register
- PSHA
- loop:
- STAB PAGE_ADDR ;// set source page
- LDAA 1,X+ ;// load value
- MOVB 4,SP, PAGE_ADDR ;// set destination page
- STAA 1,Y+
- CPX 1,SP
- BNE loop
- LDAA 5,SP+ ;// restore old page value and release stack
- STAA PAGE_ADDR ;// store it into page register
- _SRET ;// debug info only: This is the last instr of a function with a special return
- RTS
- }
- #endif
- }
- /*--------------------------- _FAR_COPY --------------------------------
- The _FAR_COPY runtime routine was used to copied large memory blocks in previous compiler releases.
- However this release now does use _FAR_COPY_RC instead. The only difference is how the size of
- the area to be copied is passed into the function. For _FAR_COPY the size is passed on the stack just
- above the return address. _FAR_COPY_RC does expect the return address just after the JSR _FAR_COPY_RC call
- in the code of the caller. This allows for denser code calling _FAR_COPY_RC but does also need a slightly
- larger runtime routine and it is slightly slower.
- The _FAR_COPY routine is here now mainly for compatibility with previous releases.
- The current compiler does not use it.
-
- --------------------------- _FAR_COPY ----------------------------------*/
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY(void) {
- #if USE_SEVERAL_PAGES
- __asm {
- DEX ;// source addr-=1, because loop counter ends at 1
- PSHX ;// save source offset
- PSHD ;// save both pages
- DEY ;// destination addr-=1, because loop counter ends at 1
- PSHY ;// save destination offset
- LDX 8,SP ;// load counter, assuming counter > 0
- loop:
- LDD 4,SP ;// load source offset
- LEAY D,X ;// calculate actual source address
- LDAB 2,SP ;// load source page
- __PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
- PSHB ;// save value
- LDD 0+1,SP ;// load destination offset
- LEAY D,X ;// calculate actual destination address
- PULA ;// restore value
- LDAB 3,SP ;// load destination page
- __PIC_JSR(_STORE_FAR_8) ;// store one byte
- DEX
- BNE loop
- LDX 6,SP ;// load return address
- LEAS 10,SP ;// release stack
- JMP 0,X ;// return
- }
- #else
- __asm {
- PSHD ;// store page registers
- TFR X,D
- ADDD 4,SP ;// calculate source end address
- STD 4,SP
- PULB ;// reload source page
- LDAA PAGE_ADDR ;// save page register
- PSHA
- loop:
- STAB PAGE_ADDR ;// set source page
- LDAA 1,X+ ;// load value
- MOVB 1,SP, PAGE_ADDR ;// set destination page
- STAA 1,Y+
- CPX 4,SP
- BNE loop
- LDAA 2,SP+ ;// restore old page value and release stack
- STAA PAGE_ADDR ;// store it into page register
- LDX 4,SP+ ;// release stack and load return address
- JMP 0,X ;// return
- }
- #endif
- }
- #else /* __HCS12X__ */
- /*
- The HCS12X knows two different kind of addresses:
- - Logical addresses. E.g.
- MOVB #page(var),RPAGE
- INC var
- - Global addresses E.g.
- MOVB #page(var),GPAGE
- GLDAA var
- INCA
- GSTAA var
- Global addresses are used with G-Load's and G-Store's, logical addresses are used for all the other instructions
- and occasions. As HC12's or HCS12's do not have the G-Load and G-Store instructions,
- global addresses are not used with these processor families.
- They are only used with HCS12X chips (and maybe future ones deriving from a HCS12X).
- Logical and Global addresses can point to the same object, however the global and logical address of an object
- are different for most objects (actually for all except the registers from 0 to 0x7FF).
- Therefore the compiler needs to transform in between them.
- HCS12X Pointer types:
- The following are logical addresses:
- - all 16 bit pointers
- - "char* __near": always.
- - "char *" in the small and banked memory model
- - 24 bit dpage, epage, ppage or rpage pointers (*1) (note: the first HCS12X compilers may not support these pointer types)
- - "char *__dpage": Note this type only exists for
- orthogonality with the HC12 A4 chip which has a DPAGE reg.
- It does not apply to the HCS12X.
- - "char *__epage": 24 bit pointer using the EPAGE register
- - "char *__ppage": 24 bit pointer using the PPAGE register.
- As the PPAGE is also used for BANKED code,
- using this pointer type is only legal from non banked code.
- - "char *__rpage": 24 bit pointer using the RPAGE register
- The following are global addresses:
- "char*": in the large memory model (only HCS12X)
- "char* __far": always for HCS12X.
- (*1): For the HC12 and HCS12 "char* __far" and "char*" in the large memory model are also logical.
- Some notes for the HC12/HCS12 programmers.
- The address of a far object for a HC12 and for a HCS12X is different, even if they are at the same place in the memory map.
- For the HC12, a far address is using the logical addresses, for the HCS12X however, far addresses are using global addresses.
- This does cause troubles for the unaware!
-
- The conversion routines implemented in this file support the special HCS12XE RAM mapping (when RAMHM is set).
- To enable this mapping compile this file with the "-MapRAM" compiler option.
- HCS12X Logical Memory map
- Logical Addresses Used for shadowed at page register Global Address
- 0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
- 0x??0800 .. 0x??0BFF Paged EEPROM EPAGE (@0x17) 0x100000+EPAGE*0x0400
- 0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
- 0x??1000 .. 0x??1FFF Paged RAM RPAGE (@0x16) 0x000000+RPAGE*0x1000
- 0x002000 .. 0x003FFF Non Paged RAM 0xFE1000..0xFF1FFF Not Paged 0x0FE000
- 0x004000 .. 0x007FFF Non Paged FLASH 0xFC8000..0xFCBFFF Not Paged 0x7F4000
- 0x??8000 .. 0x00BFFF Paged FLASH PPAGE (@0x30) 0x400000+PPAGE*0x4000
- 0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
- NA: Not Applicable
- HCS12X Global Memory map
- Global Addresses Used for Logical mapped at
- 0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
- 0x000800 .. 0x000FFF DMA registers Not mapped
- 0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
- 0x0FE000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x003FFF
- 0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
- 0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
- 0x140000 .. 0x3FFFFF External Space Not mapped
- 0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
- 0x7F4000 .. 0x7F7FFF FLASH, Log non paged 0x004000 .. 0x007FFF
- 0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
- HCS12XE Logical Memory map (with RAMHM set)
- Logical Addresses Used for shadowed at page register Global Address
- 0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
- 0x??0800 .. 0x??0BFF Paged EEPROM EPAGE 0x100000+EPAGE*0x0400
- 0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
- 0x??1000 .. 0x??1FFF Paged RAM RPAGE 0x000000+RPAGE*0x1000
- 0x002000 .. 0x003FFF Non Paged RAM 0xFA1000..0xFB1FFF Not Paged 0x0FA000
- 0x004000 .. 0x007FFF Non Paged RAM 0xFC1000..0xFF1FFF Not Paged 0x0FC000
- 0x??8000 .. 0x00BFFF Paged FLASH PPAGE 0x400000+PPAGE*0x4000
- 0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
- NA: Not Applicable
- HCS12X Global Memory map (with RAMHM set)
- Global Addresses Used for Logical mapped at
- 0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
- 0x000800 .. 0x000FFF DMA registers Not mapped
- 0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
- 0x0FA000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x007FFF
- 0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
- 0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
- 0x140000 .. 0x3FFFFF External Space Not mapped
- 0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
- 0x7F4000 .. 0x7F7FFF FLASH, Log non paged Not mapped
- 0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
- How to read this table:
- For logical addresses, the lower 16 bits of the address do determine in which area the address is,
- if this address is paged, then this entry also controls and which of the EPAGE, PPAGE or RPAGE
- page register is controlling the bits 16 to 23 of the address.
- For global addresses, the bits 16 to 23 have to be in the GPAGE register and the lower 16 bits
- have to be used with the special G load or store instructions (e.g. GLDAA).
- As example the logical address 0x123456 is invalid. Because its lower bits 0x3456 are in a
- non paged area, so the page 0x12 does not exist.
- The address 0xFE1020 however does exist. To access it, the RPAGE has to contain 0xFE and the
- offset 0x1020 has to be used.
- ORG $7000
- MOVB #0xFE, 0x16 ; RPAGE
- LDAA 0x1020 ; reads at the logical address 0xFE1020
- Because the last two RAM pages are also accessible directly from 0x2000 to 0x3FFF, the
- following shorter code does read the same memory location:
- ORG $7000
- LDAA 0x2020 ; reads at the logical address 0x2020
- ; which maps to the same memory as 0xFE1020
- This memory location also has a global address. For logical 0xFE1020 the global address is 0x0FE020.
- So the following code does once more access the same memory location:
- ORG $7000
- MOVB #0x0F, 0x10 ; GPAGE
- GLDAA 0xE020 ; reads at the global address 0x0FE020
- ; which maps to the same memory as the logical addr. 0xFE1020
- Therefore every memory location for the HCS12X has up to 3 different addresses.
- Up to two logical and one global.
- Notes.
- - Not every address has a logical equivalent. The external space is only available in the global address space.
- - The PPAGE must only be set if the code is outside of the 0x8000 to 0xBFFF range.
- If not, the next code fetch will be from the new wrong PPAGE value.
- - Inside of the paged area, the highest pages are allocated first. So all HCS12X's do have the FF pages
- (if they have this memory type at all).
- - For RPAGE, the value 0 is illegal. Otherwise the global addresses would overlap with the registers.
- */
- #if __OPTION_ACTIVE__("-MapRAM")
- #define __HCS12XE_RAMHM_SET__
- #endif
- /*--------------------------- pointer conversion operations -------------------------------*/
- /*--------------------------- _CONV_GLOBAL_TO_LOGICAL --------------------------------
- Convert 24 bit logical to 24 bit global pointer
- ("char*__far" to "char*__gpage")
- Arguments :
- - B : page part of global address
- - X : 16 offset part of global address
- Postcondition :
- - B == page of returned logical address
- - X == offset of returned logical address
- - Y remains unchanged
- - A remains unchanged
- */
- /*--------------------------- Convert 24 bit global to 24 bit logical pointer ----------------------------------*/
- /* B:X = Logical(B:X) */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_FRAME
- #pragma NO_ENTRY
- #pragma NO_EXIT
- void NEAR _CONV_GLOBAL_TO_LOGICAL(void) {
- __asm {
- CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
- BLO Below400000
- // from 0x400000 to 0x7FFFFF
- CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
- BNE PAGED_FLASH_AREA
- #ifndef __HCS12XE_RAMHM_SET__
- BITX #0x4000
- BEQ PAGED_FLASH_AREA
- #else
- CPX #0xC000
- BLO PAGED_FLASH_AREA
- #endif
- // from 0x7F4000 to 0x7F7FFF or 0x7FC000 to 0x7FFFFF
- ;// Note: offset in X is already OK.
- CLRB ;// logical page == 0
- RTS
- PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
- // from 0x400000 to 0x7F3FFF or 0x7F8000 to 0x7FBFFF
- LSLX ; // shift 24 bit address 2 bits to the left to get correct page in B
- ROLB
- LSLX
- ROLB
- LSRX ; // shift back to get offset from 0x8000 to 0xBFFF
- SEC
- RORX
- RTS ;// done
- Below400000:
- // from 0x000000 to 0x3FFFFF
- #if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
- CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
- BLO Below140000
- ERROR !!!! ;// this mapping is not possible! What should we do?
- RTS
- Below140000:
- // from 0x000000 to 0x13FFFF
- #endif
- CMPB #0x10 ;// if >= 0x100000 it's EEPROM
- BLO Below100000
- // from 0x100000 to 0x13FFFF (or 0x3FFFFF)
- CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
- BLO Below13FC00
- CPX #0xFC00
- BLO Below13FC00
- // from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
- LEAX 0x1000,X ;// same as SUBX #0xF000 // map from 0xFC00 to 0x0C00
- CLRB
- RTS
- Below13FC00:
- // from 0x100000 to 0x13FBFF
- PSHA
- TFR XH,A ;// calculate logical page
- EXG A,B
- LSRD
- LSRD
- PULA
- ANDX #0x03FF
- LEAX 0x0800,X ;// same as ORX #0x0800
- RTS
- Below100000:
- // from 0x000000 to 0x0FFFFF
- TSTB
- BNE RAM_AREA
- CPX #0x1000
- BLO Below001000
- RAM_AREA:
- // from 0x001000 to 0x0FFFFF
- CMPB #0x0F
- BNE PagedRAM_AREA
- #ifndef __HCS12XE_RAMHM_SET__
- CPX #0xE000
- BLO PagedRAM_AREA
- // from 0x0FE000 to 0x0FFFFF
- SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
- #else
- CPX #0xA000
- BLO PagedRAM_AREA
- // from 0x0FA000 to 0x0FFFFF
- SUBX #(0xA000-0x2000) ;// map 0xA000 to 0x2000
- #endif
- CLRB ;// Page is 0
- RTS
- PagedRAM_AREA:
- // from 0x001000 to 0x0FDFFF
- PSHA
- TFR XH, A ;// calculate logical page
- EXG A,B
- LSRD
- LSRD
- LSRD
- LSRD
- PULA
- ANDX #0x0FFF
- LEAX 0x1000,X ;// same as ORX #0x1000
- RTS
- Below001000:
- // from 0x000000 to 0x000FFF
- #if 0
- CMPA #0x08
- BLO Below000800
- // from 0x000800 to 0x000FFF
- // ??? DMA Regs?
- RTS
- Below000800:
- // from 0x000000 to 0x0007FF
- #endif
- CLRB
- RTS
- }
- }
- /*--------------------------- _CONV_GLOBAL_TO_NEAR --------------------------------
- Convert 24 bit global to 16 bit logical pointer
- ("char*__far" to "char*")
- Arguments :
- - B : page part of global address
- - X : 16 offset part of global address
- Postcondition :
- - B is undefined
- - A remains unchanged
- - X == offset of returned logical address
- - Y remains unchanged
- */
- /*--------------------------- Convert 24 bit global to 16 bit logical pointer ----------------------------------*/
- /* X = Logical(B:X) */
- #ifdef __cplusplus
- extern "C"
- #endif
- #define _REUSE_CONV_GLOBAL_TO_LOGICAL 1
- #pragma NO_FRAME
- #pragma NO_ENTRY
- #pragma NO_EXIT
- void NEAR _CONV_GLOBAL_TO_NEAR(void){
- #if _REUSE_CONV_GLOBAL_TO_LOGICAL /* do we want an optimized version? */
- __asm JMP _CONV_GLOBAL_TO_LOGICAL; /* offset for NEAR is same as for LOGICAL. */
- #else
- __asm {
- CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
- BLO Below400000
- // from 0x400000 to 0x7FFFFF
- #ifndef __HCS12XE_RAMHM_SET__
- CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
- BNE PAGED_FLASH_AREA
- CPX #0x4000
- BLO PAGED_FLASH_AREA
- // from 0x7F4000 to 0x7FFFFF
- #else
- CMPB #0x7F ;// check for Unpaged area 0x7FC000..0x7FFFFF
- BNE PAGED_FLASH_AREA
- CPX #0xC000
- BLO PAGED_FLASH_AREA
- // from 0x7FC000 to 0x7FFFFF
- #endif
- ;// note non PAGED flash areas or paged area 0x7F8000..0x7FBFFF which are mapping all correctly
- RTS
- PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
- // from 0x400000 to 0x7F3FFF
- ANDX #0x3F00 ;// cut to 0.. 0x3FFF
- LEAX 0x8000,X ;// same as ORX #0x8000 ;// move to 0x8000..0xBFFF
- RTS ;// done
- Below400000:
- // from 0x000000 to 0x3FFFFF
- #if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
- CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
- BLO Below140000
- ERROR !!!! ;// this mapping is not possible! What should we do?
- RTS
- Below140000:
- // from 0x000000 to 0x13FFFF
- #endif
- CMPB #0x10 ;// if >= 0x100000 it's EEPROM
- BLO Below100000
- // from 0x100000 to 0x13FFFF (or 0x3FFFFF)
- CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
- BNE Below13FC00
- CPX #0xFC00
- BLO Below13FC00
- // from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
- SUBX #0xF000 ;// map from 0xFC00 to 0x0C00
- RTS
- Below13FC00:
- // from 0x100000 to 0x13FBFF
- ANDX #0x03FF
- LEAX 0x800,X ;// same as ORX #0x0800
- RTS
- Below100000:
- // from 0x000000 to 0x0FFFFF
- TBNE B,RAM_AREA
- CPX #0x1000
- BLO Below001000
- RAM_AREA:
- // from 0x001000 to 0x0FFFFF
- CMPB #0x0F
- BNE PagedRAM_AREA
- #ifndef __HCS12XE_RAMHM_SET__
- CPX #0xE000
- BLO PagedRAM_AREA
- // from 0x0FE000 to 0x0FFFFF
- SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
- #else
- CPX #0xA000
- BLO PagedRAM_AREA
- // from 0x0FA000 to 0x0FFFFF
- SUBX #(0xA000-0x2000) ;// map 0xA000 to 0x2000
- #endif
- RTS
- PagedRAM_AREA:
- // from 0x001000 to 0x0FDFFF (0x001000 to 0x0F9FFF if HCS12XE RAM mapping is enabled)
- ANDX #0x0FFF
- LEAX 0x1000,X ;// same as ORX #0x1000
- RTS
- Below001000:
- // from 0x000000 to 0x000FFF
- RTS
- }
- #endif
- }
- /*--------------------------- _CONV_NEAR_TO_GLOBAL --------------------------------
- Convert 16 bit logical to 24 bit global pointer
- ("char*__near" to "char*__far")
- Arguments :
- - X : 16 bit near pointer
- Postcondition :
- - B == page of returned global address
- - X == offset of returned global address
- - Y remains unchanged
- - A is unspecified
- */
- /*--------------------------- Convert 16 bit logical to 24 bit global pointer ----------------------------------*/
- /* B:X = Global(X) */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_FRAME
- #pragma NO_ENTRY
- #pragma NO_EXIT
- void NEAR _CONV_NEAR_TO_GLOBAL(void){
- __asm {
- // syntax:
- // input 16 bit offset is bit15..bit0
- // ppage values: ppage7..ppage0
- // epage values: epage7..epage0
- // dpage values: dpage7..dpage0
- // rpage values: rpage7..rpage0
- PSHX ;// D contains bit15..bit0
- TFR X,D ;// D is cheaper to shift
- LSLD ;// D contains 0 bit14..bit0, C contains bit15
- BCC Below8000 ;// bit15 == 0?
- // from 0x8000 to 0xFFFF
- LSLD ;// D contains 00 bit13..bit0, C contains bit14
- BCC BelowC000
- LDAB #0x7F
- PULX
- RTS ;// returns 0b0111 1111 11 bit13...bit0
- BelowC000: ;// from 0x8000 to 0xBFFF
- TFR D,X
- LDAB __PPAGE_ADR__
- SEC
- RORB
- RORX
- LSRB
- RORX
- LEAS 2,SP
- RTS ;// returns 0b01 ppage7..ppage0 bit13...bit0
- Below8000:
- LSLD ;// D contains 00 bit13..bit0, C contains bit14
- BCC Below4000
- // from 0x4000 to 0x7FFF
- PULX
- #ifndef __HCS12XE_RAMHM_SET__
- LDAB #0x7F
- #else
- LEAX (0xC000-0x4000),X
- LDAB #0x0F
- #endif
- RTS ;// returns 0b0111 1111 01 bit13...bit0
- Below4000:
- LSLD ;// D contains 000 bit12..bit0, C contains bit13
- BCC Below2000
- // from 0x2000 to 0x3FFF
- PULX
- #ifndef __HCS12XE_RAMHM_SET__
- LEAX (0xE000-0x2000),X
- #else
- LEAX (0xA000-0x2000),X
- #endif
- LDAB #0x0F
- RTS ;// returns 0b0000 1111 111 bit12...bit0
- Below2000:
- LSLD ;// D contains 0000 bit11..bit0, C contains bit12
- BCC Below1000
- // from 0x1000 to 0x1FFF
- LDAB __RPAGE_ADR__
- LDAA #0x10
- MUL
- EORB 0,SP
- EORB #0x10 ;// clear 1 bit
- STAB 0,SP
- TFR A,B
- PULX
- RTS
- Below1000:
- LSLD ;// D contains 0000 0 bit10..bit0, C contains bit11
- BCC Below0800
- // from 0x0800 to 0x0FFF
- LSLD ;// D contains 0000 00 bit9..bit0, C contains bit10
- BCC Below0C00
- // from 0x0C00 to 0x0FFF
- LDAB #0x13
- PULX
- LEAX 0xF000,X
- RTS ;// returns 0b0001 0011 1111 11 bit9...bit0
- Below0C00:
- // from 0x0800 to 0x0BFF
- LDAB __EPAGE_ADR__
- LDAA #0x04
- MUL
- EORB 0,SP
- EORB #0x08
- STAB 0,SP
- TFR A,B
- ORAB #0b00010000
- PULX
- RTS
- Below0800:
- PULX
- CLRB
- RTS
- }
- }
- /*--------------------------- _CONV_STACK_NEAR_TO_GLOBAL --------------------------------
- Convert 16 bit logical of address on the stack 24 bit global pointer
- ("char*__near" to "char*__far")
- Arguments :
- - X : 16 bit near pointer
- Postcondition :
- - B == page of returned global address
- - X == offset of returned global address
- - Y remains unchanged
- - A is unspecified
- */
- /*--------------------------- Convert 16 bit logical stack address to 24 bit global pointer ----------------------------------*/
- /* B:X = Global(D) */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_FRAME
- #pragma NO_ENTRY
- #pragma NO_EXIT
- void NEAR _CONV_STACK_NEAR_TO_GLOBAL(void){
- __asm {
- // syntax:
- // input 16 bit offset is bit15..bit0
- // ppage values: ppage7..ppage0
- // epage values: epage7..epage0
- // dpage values: dpage7..dpage0
- // rpage values: rpage7..rpage0
- // stack must be between $1000 and $3FFF.
- // actually placing the stack at $1000 implies that the RPAGE register is not set (and correctly initialized)
- CPX #0x2000
- BLO PAGED_RAM
- // Map 0x2000 to 0x0FE000 (0x0FA000 for HCS12XE RAM mapping is enabled)
- LDAB #0x0F
- #ifndef __HCS12XE_RAMHM_SET__
- LEAX (0xE000-0x2000),X ;// LEAX is one cycle faster than ADDX #
- #else
- LEAX (0xA000-0x2000),X ;// LEAX is one cycle faster than ADDX #
- #endif
- RTS
- PAGED_RAM:
- PSHX
- LDAB __RPAGE_ADR__
- LDAA #0x20
- MUL
- EORB 0,SP
- EORB #0x10 ;// clear 1 bit
- STAB 0,SP
- TFR A,B
- PULX
- RTS
- }
- }
- /*--------------------------- _CONV_LOGICAL_TO_GLOBAL --------------------------------
- Convert 24 bit global to 24 bit logical pointer
- ("char*__far" to "char*__gpage")
- Arguments :
- - B : page part of logical address
- - X : 16 offset part of logical address
- Postcondition :
- - B == page of returned global address
- - X == offset of returned global address
- - Y remains unchanged
- - A remains unchanged
- */
- /*--------------------------- Convert 24 bit logical to 24 bit global pointer ----------------------------------*/
- /* B:X = Logical(B:X) */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_FRAME
- #pragma NO_ENTRY
- #pragma NO_EXIT
- void NEAR _CONV_LOGICAL_TO_GLOBAL(void) {
- __asm {
- // syntax:
- // input 16 bit offset is bit15..bit0
- // ppage values: ppage7..ppage0
- // epage values: epage7..epage0
- // dpage values: dpage7..dpage0
- // rpage values: rpage7..rpage0
- PSHA ;// save A across this routine.
- PSHX ;// D contains bit15..bit0
- PSHB ;// store page
- TFR X,D ;// D is cheaper to shift
- LSLD ;// D contains 0 bit14..bit0, C contains bit15
- BCC Below8000 ;// bit15 == 0?
- // from 0x8000 to 0xFFFF
- LSLD ;// D contains 00 bit13..bit0, C contains bit14
- BCC BelowC000
- PULB ;// cleanup stack
- LDAB #0x7F
- PULX
- PULA
- RTS ;// returns 0b0111 1111 11 bit13...bit0
- BelowC000: ;// from 0x8000 to 0xBFFF
- TFR D,X
- PULB ;// cleanup stack
- SEC
- RORB
- RORX
- LSRB
- RORX
- LEAS 2,SP
- PULA
- RTS ;// returns 0b01 ppage7..ppage0 bit13...bit0
- Below8000:
- LSLD ;// D contains 00 bit13..bit0, C contains bit14
- BCC Below4000
- ;// from 0x4000 to 0x7FFF
- PULB ;// cleanup stack
- PULX
- #ifndef __HCS12XE_RAMHM_SET__
- LDAB #0x7F
- #else
- LEAX (0xC000-0x4000),X
- LDAB #0x0F
- #endif
- PULA
- RTS ;// returns 0b0111 1111 01 bit13...bit0
- Below4000:
- LSLD ;// D contains 000 bit12..bit0, C contains bit13
- BCC Below2000
- // from 0x2000 to 0x3FFF
- PULB ;// cleanup stack
- PULX
- #ifndef __HCS12XE_RAMHM_SET__
- LEAX (0xE000-0x2000),X
- #else
- LEAX (0xA000-0x2000),X
- #endif
- LDAB #0x0F
- PULA
- RTS ;// returns 0b0000 1111 111 bit12...bit0
- Below2000:
- LSLD ;// D contains 0000 bit11..bit0, C contains bit12
- BCC Below1000
- // from 0x1000 to 0x1FFF
- PULB
- LDAA #0x10
- MUL
- EORB 0,SP
- EORB #0x10 ;// clear 1 bit
- STAB 0,SP
- TFR A,B
- PULX
- PULA
- RTS
- Below1000:
- LSLD ;// D contains 0000 0 bit10..bit0, C contains bit11
- BCC Below0800
- // from 0x0800 to 0x0FFF
- LSLD ;// D contains 0000 00 bit9..bit0, C contains bit10
- BCC Below0C00
- // from 0x0C00 to 0x0FFF
- PULB ;// cleanup stack
- LDAB #0x13
- PULX
- LEAX 0xF000,X
- PULA
- RTS ;// returns 0b0001 0011 1111 11 bit9...bit0
- Below0C00:
- // from 0x0800 to 0x0BFF
- PULB
- LDAA #0x04
- MUL
- EORB 0,SP
- EORB #0x08
- STAB 0,SP
- TFR A,B
- ORAB #0b00010000
- PULX
- PULA
- RTS
- Below0800:
- PULB
- PULX
- PULA
- CLRB
- RTS
- }
- }
- /*--------------------------- _FAR_COPY_RC HCS12X Routines --------------------------------
- copy larger far memory blocks
- There are the following memory block copy routines:
- _COPY : 16 bit logical copies.
- Src and dest are both near. Note: implemented in rtshc12.c and not here.
- _FAR_COPY_RC HC12/HCS12 struct copy routine.
- Expects HC12/HCS12 logical 24 bit address.
- Note: Does not exist for the HCS12X.
- The HC12/HCS12 implementation is implemented above.
- _FAR_COPY_GLOBAL_GLOBAL_RC:
- _FAR_COPY_GLOBAL_LOGICAL_RC:
- _FAR_COPY_LOGICAL_GLOBAL_RC:
- _FAR_COPY_LOGICAL_LOGICAL_RC:
- _FAR_COPY_NEAR_GLOBAL_RC:
- _FAR_COPY_NEAR_LOGICAL_RC:
- _FAR_COPY_GLOBAL_NEAR_RC:
- _FAR_COPY_LOGICAL_NEAR_RC: HCS12X specific far copy routine. The name describes what the src/dest address format are.
- All near src arguments are passed in X, all 24 bit src in X/B.
- All near dest arguments are passed in Y, all 24 bit src in Y/A.
- (Note: HC12 _FAR_COPY_RC is using X/A as src and Y/B as dest, so the register usage is not the same!)
- Arguments :
- - B:X : src address (for NEAR/_COPY: only X)
- - A:Y : dest address (for NEAR/_COPY: only Y)
- - number of bytes to be copied behind return address (for _COPY: in D register). The number of bytes is always > 0
- Result :
- - memory area copied
- - no registers are saved, i.e. all registers may be destroyed
- - for _COPY: D contains 0.
- - for HCS12X _FAR_COPY_... routines: GPAGE state is unknown
- */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_GLOBAL_GLOBAL_RC(void) {
- __asm {
- PSHD
- PSHY
- LDY 4,SP ;// load return address
- LDD 2,Y+ ;// load size
- STY 4,SP ;// store return address
- PULY
- PSHD
- LDAB 3,SP
- Loop:
- STAB __GPAGE_ADR__
- GLDAA 1,X+
- MOVB 2,SP,__GPAGE_ADR__
- GSTAA 1,Y+
- DECW 0,SP
- BNE Loop
- LEAS 4,SP
- _SRET ;// debug info only: This is the last instr of a function with a special return
- RTS
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _SET_PAGE_REG_HCS12X(void) {
- // Sets the page contained in A to the register controlling the logical addr contained in X.
- // saves the old page before and returns it in A together with the page address just below the return address.
- // X/Y both remain valid.
- __asm {
- PSHX
- // 0000..FFFF
- CPX #0x8000
- BLO _LO8000
- LDX #__PPAGE_ADR__
- BRA Handle
- _LO8000:
- // 0000..7FFF
- CPX #0x1000
- BLO _LO1000
- LDX #__RPAGE_ADR__
- BRA Handle
- _LO1000:
- LDX #__EPAGE_ADR__
- Handle:
- LDAA 0,X ;// load old page register content
- STAB 0,X ;// set new page register
- STX 4,SP
- PULX
- RTS
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_GLOBAL_LOGICAL_RC(void) {
- __asm {
- STAB __GPAGE_ADR__
- EXG X,Y
- TFR A,B
- PSHY ;// space to store size
- PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
- LDY 4,SP ;// load return address
- LDX 2,Y+ ;// load size
- STY 4,SP
- LDY 2,SP ;// restore dest pointer
- STX 2,SP ;// store size
- LDX 0,SP ;// reload src pointer
- __PIC_JSR(_SET_PAGE_REG_HCS12X)
- Loop: GLDAB 1,Y+
- STAB 1,X+
- DECW 2,SP
- BNE Loop
- PULX ;// reload page register address
- STAA 0,X ;// restore old page content (necessary if it was PPAGE)
- PULX ;// clean up stack
- _SRET ;// debug info only: This is the last instr of a function with a special return
- RTS
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_LOGICAL_GLOBAL_RC(void) {
- __asm {
- STAA __GPAGE_ADR__
- PSHY ;// space to store size
- PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
- LDY 4,SP ;// load return address
- LDX 2,Y+ ;// load size
- STY 4,SP
- LDY 2,SP ;// restore dest pointer
- STX 2,SP ;// store size
- LDX 0,SP ;// reload src pointer
- __PIC_JSR(_SET_PAGE_REG_HCS12X)
- Loop: LDAB 1,X+
- GSTAB 1,Y+
- DECW 2,SP
- BNE Loop
- PULX
- STAA 0,X ;// restore old page content (necessary if it was PPAGE)
- PULX ;// clean up stack
- _SRET ;// debug info only: This is the last instr of a function with a special return
- RTS
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_LOGICAL_LOGICAL_RC(void) {
- __asm {
- PSHA
- __PIC_JSR(_CONV_LOGICAL_TO_GLOBAL);
- PULA
- __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_NEAR_GLOBAL_RC(void) {
- __asm {
- CLRB
- __PIC_JMP(_FAR_COPY_LOGICAL_GLOBAL_RC);
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_NEAR_LOGICAL_RC(void) {
- __asm {
- PSHA
- __PIC_JSR(_CONV_NEAR_TO_GLOBAL);
- PULA
- __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_GLOBAL_NEAR_RC(void) {
- __asm {
- CLRA /* near to logical (we may have to use another runtime if this gets non trivial as well :-( */
- __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
- }
- }
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_LOGICAL_NEAR_RC(void) {
- __asm {
- EXG A,B
- EXG X,Y
- PSHA
- __PIC_JSR(_CONV_NEAR_TO_GLOBAL);
- PULA
- EXG A,B
- EXG X,Y
- __PIC_JMP(_FAR_COPY_LOGICAL_GLOBAL_RC);
- }
- }
- /* _FAR_COPY_LOGICAL_GLOBAL: is used by some old wizard generated projects. Not used by current setup anymore */
- #ifdef __cplusplus
- extern "C"
- #endif
- #pragma NO_ENTRY
- #pragma NO_EXIT
- #pragma NO_FRAME
- void NEAR _FAR_COPY_LOGICAL_GLOBAL(void) {
- __asm {
- STAA __GPAGE_ADR__
- PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
- __PIC_JSR(_SET_PAGE_REG_HCS12X)
- Loop: LDAB 1,X+
- GSTAB 1,Y+
- DECW 4,SP
- BNE Loop
- PULX
- STAA 0,X ;// restore old page content (necessary if it was PPAGE)
- LDX 4,SP+ ;// load return address and clean stack
- JMP 0,X
- }
- }
- #endif /* __HCS12X__ */
- /*----------------- end of code ------------------------------------------------*/
|