datapage.c 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970
  1. /******************************************************************************
  2. FILE : datapage.c
  3. PURPOSE : paged data access runtime routines
  4. MACHINE : Freescale 68HC12 (Target)
  5. LANGUAGE : ANSI-C
  6. HISTORY : 21.7.96 first version created
  7. ******************************************************************************/
  8. #include "hidef.h"
  9. #include "non_bank.sgm"
  10. #include "runtime.sgm"
  11. #ifndef __HCS12X__ /* it's different for the HCS12X. See the text below at the #else // __HCS12X__ */
  12. /*
  13. According to the -Cp option of the compiler the
  14. __DPAGE__, __PPAGE__ and __EPAGE__ macros are defined.
  15. If none of them is given as argument, then no page accesses should occur and
  16. this runtime routine should not be used !
  17. To be on the save side, the runtime routines are created anyway.
  18. If some of the -Cp options are given an adapted versions which only covers the
  19. needed cases is produced.
  20. */
  21. /* if no compiler option -Cp is given, it is assumed that all possible are given : */
  22. /* Compile with option -DHCS12 to activate this code */
  23. #if defined(HCS12) || defined(_HCS12) || defined(__HCS12__) /* HCS12 family has PPAGE register only at 0x30 */
  24. #define PPAGE_ADDR (0x30+REGISTER_BASE)
  25. #ifndef __PPAGE__ /* may be set already by option -CPPPAGE */
  26. #define __PPAGE__
  27. #endif
  28. /* Compile with option -DDG128 to activate this code */
  29. #elif defined DG128 /* HC912DG128 derivative has PPAGE register only at 0xFF */
  30. #define PPAGE_ADDR (0xFF+REGISTER_BASE)
  31. #ifndef __PPAGE__ /* may be set already by option -CPPPAGE */
  32. #define __PPAGE__
  33. #endif
  34. #elif defined(HC812A4)
  35. /* all setting default to A4 already */
  36. #endif
  37. #if !defined(__EPAGE__) && !defined(__PPAGE__) && !defined(__DPAGE__)
  38. /* as default use all page registers */
  39. #define __DPAGE__
  40. #define __EPAGE__
  41. #define __PPAGE__
  42. #endif
  43. /* modify the following defines to your memory configuration */
  44. #define EPAGE_LOW_BOUND 0x400u
  45. #define EPAGE_HIGH_BOUND 0x7ffu
  46. #define DPAGE_LOW_BOUND 0x7000u
  47. #define DPAGE_HIGH_BOUND 0x7fffu
  48. #define PPAGE_LOW_BOUND (DPAGE_HIGH_BOUND+1)
  49. #define PPAGE_HIGH_BOUND 0xBFFFu
  50. #define REGISTER_BASE 0x0u
  51. #ifndef DPAGE_ADDR
  52. #define DPAGE_ADDR (0x34u+REGISTER_BASE)
  53. #endif
  54. #ifndef EPAGE_ADDR
  55. #define EPAGE_ADDR (0x36u+REGISTER_BASE)
  56. #endif
  57. #ifndef PPAGE_ADDR
  58. #define PPAGE_ADDR (0x35u+REGISTER_BASE)
  59. #endif
  60. /*
  61. The following parts about the defines are assumed in the code of _GET_PAGE_REG :
  62. - the memory region controlled by DPAGE is above the area controlled by the EPAGE and
  63. below the area controlled by the PPAGE.
  64. - the lower bound of the PPAGE area is equal to be the higher bound of the DPAGE area + 1
  65. */
  66. #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
  67. #error /* please adapt _GET_PAGE_REG for this non default page configuration */
  68. #endif
  69. #if DPAGE_HIGH_BOUND+1 != PPAGE_LOW_BOUND
  70. #error /* please adapt _GET_PAGE_REG for this non default page configuration */
  71. #endif
  72. /* this module does either control if any access is in the bounds of the specified page or */
  73. /* ,if only one page is specified, just use this page. */
  74. /* This behavior is controlled by the define USE_SEVERAL_PAGES. */
  75. /* If !USE_SEVERAL_PAGES does increase the performance significantly */
  76. /* NOTE : When !USE_SEVERAL_PAGES, the page is also set for accesses outside of the area controlled */
  77. /* 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 */
  78. #if !defined(__DPAGE__) && !defined(__EPAGE__) && !defined(__PPAGE__)
  79. /* no page at all is specified */
  80. /* only specifying the right pages will speed up these functions a lot */
  81. #define USE_SEVERAL_PAGES 1
  82. #elif defined(__DPAGE__) && defined(__EPAGE__) || defined(__DPAGE__) && defined(__PPAGE__) || defined(__EPAGE__) && defined(__PPAGE__)
  83. /* more than one page register is used */
  84. #define USE_SEVERAL_PAGES 1
  85. #else
  86. #define USE_SEVERAL_PAGES 0
  87. #if defined(__DPAGE__) /* check which pages are used */
  88. #define PAGE_ADDR PPAGE_ADDR
  89. #elif defined(__EPAGE__)
  90. #define PAGE_ADDR EPAGE_ADDR
  91. #elif defined(__PPAGE__)
  92. #define PAGE_ADDR PPAGE_ADDR
  93. #else /* we do not know which page, decide it at runtime */
  94. #error /* must not happen */
  95. #endif
  96. #endif
  97. #if USE_SEVERAL_PAGES /* only needed for several pages support */
  98. /*--------------------------- _GET_PAGE_REG --------------------------------
  99. Runtime routine to detect the right register depending on the 16 bit offset part
  100. of an address.
  101. This function is only used by the functions below.
  102. Depending on the compiler options -Cp different versions of _GET_PAGE_REG are produced.
  103. Arguments :
  104. - Y : offset part of an address
  105. Result :
  106. if address Y is controlled by a page register :
  107. - X : address of page register if Y is controlled by an page register
  108. - Zero flag cleared
  109. - all other registers remain unchanged
  110. if address Y is not controlled by a page register :
  111. - Zero flag is set
  112. - all registers remain unchanged
  113. --------------------------- _GET_PAGE_REG ----------------------------------*/
  114. #if defined(__DPAGE__)
  115. #ifdef __cplusplus
  116. extern "C"
  117. #endif
  118. #pragma NO_ENTRY
  119. #pragma NO_EXIT
  120. #pragma NO_FRAME
  121. static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
  122. __asm {
  123. L_DPAGE:
  124. CPY #DPAGE_LOW_BOUND ;// test of lower bound of DPAGE
  125. #if defined(__EPAGE__)
  126. BLO L_EPAGE ;// EPAGE accesses are possible
  127. #else
  128. BLO L_NOPAGE ;// no paged memory below accesses
  129. #endif
  130. CPY #DPAGE_HIGH_BOUND ;// test of higher bound DPAGE/lower bound PPAGE
  131. #if defined(__PPAGE__)
  132. BHI L_PPAGE ;// EPAGE accesses are possible
  133. #else
  134. BHI L_NOPAGE ;// no paged memory above accesses
  135. #endif
  136. FOUND_DPAGE:
  137. LDX #DPAGE_ADDR ;// load page register address and clear zero flag
  138. RTS
  139. #if defined(__PPAGE__)
  140. L_PPAGE:
  141. CPY #PPAGE_HIGH_BOUND ;// test of higher bound of PPAGE
  142. BHI L_NOPAGE
  143. FOUND_PPAGE:
  144. LDX #PPAGE_ADDR ;// load page register address and clear zero flag
  145. RTS
  146. #endif
  147. #if defined(__EPAGE__)
  148. L_EPAGE:
  149. CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
  150. BLO L_NOPAGE
  151. CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
  152. BHI L_NOPAGE
  153. FOUND_EPAGE:
  154. LDX #EPAGE_ADDR ;// load page register address and clear zero flag
  155. RTS
  156. #endif
  157. L_NOPAGE:
  158. ORCC #0x04 ;// sets zero flag
  159. RTS
  160. }
  161. }
  162. #else /* !defined(__DPAGE__) */
  163. #if defined( __PPAGE__ )
  164. #ifdef __cplusplus
  165. extern "C"
  166. #endif
  167. #pragma NO_ENTRY
  168. #pragma NO_EXIT
  169. #pragma NO_FRAME
  170. static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
  171. __asm {
  172. L_PPAGE:
  173. CPY #PPAGE_LOW_BOUND ;// test of lower bound of PPAGE
  174. #if defined( __EPAGE__ )
  175. BLO L_EPAGE
  176. #else
  177. BLO L_NOPAGE ;// no paged memory below
  178. #endif
  179. CPY #PPAGE_HIGH_BOUND ;// test of higher bound PPAGE
  180. BHI L_NOPAGE
  181. FOUND_PPAGE:
  182. LDX #PPAGE_ADDR ;// load page register address and clear zero flag
  183. RTS
  184. #if defined( __EPAGE__ )
  185. L_EPAGE:
  186. CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
  187. BLO L_NOPAGE
  188. CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
  189. BHI L_NOPAGE
  190. FOUND_EPAGE:
  191. LDX #EPAGE_ADDR ;// load page register address and clear zero flag
  192. RTS
  193. #endif
  194. L_NOPAGE: ;// not in any allowed page area
  195. ;// its a far access to a non paged variable
  196. ORCC #0x04 ;// sets zero flag
  197. RTS
  198. }
  199. }
  200. #else /* !defined(__DPAGE__ ) && !defined( __PPAGE__) */
  201. #if defined(__EPAGE__)
  202. #ifdef __cplusplus
  203. extern "C"
  204. #endif
  205. #pragma NO_ENTRY
  206. #pragma NO_EXIT
  207. #pragma NO_FRAME
  208. static void NEAR _GET_PAGE_REG(void) { /*lint -esym(528, _GET_PAGE_REG) used in asm code */
  209. __asm {
  210. L_EPAGE:
  211. CPY #EPAGE_LOW_BOUND ;// test of lower bound of EPAGE
  212. BLO L_NOPAGE
  213. CPY #EPAGE_HIGH_BOUND ;// test of higher bound of EPAGE
  214. BHI L_NOPAGE
  215. FOUND_EPAGE:
  216. LDX #EPAGE_ADDR ;// load page register address and clear zero flag
  217. RTS
  218. L_NOPAGE: ;// not in any allowed page area
  219. ;// its a far access to a non paged variable
  220. ORCC #0x04 ;// sets zero flag
  221. RTS
  222. }
  223. }
  224. #endif /* defined(__EPAGE__) */
  225. #endif /* defined(__PPAGE__) */
  226. #endif /* defined(__DPAGE__) */
  227. #endif /* USE_SEVERAL_PAGES */
  228. /*--------------------------- _SET_PAGE --------------------------------
  229. Runtime routine to set the right page register. This routine is used if the compiler
  230. does not know the right page register, i.e. if the option -Cp is used for more than
  231. one page register or if the runtime option is used for one of the -Cp options.
  232. Arguments :
  233. - offset part of an address in the Y register
  234. - page part of an address in the B register
  235. Result :
  236. - page part written into the correct page register.
  237. - the old page register content is destroyed
  238. - all processor registers remains unchanged
  239. --------------------------- _SET_PAGE ----------------------------------*/
  240. #ifdef __cplusplus
  241. extern "C"
  242. #endif
  243. #pragma NO_ENTRY
  244. #pragma NO_EXIT
  245. #pragma NO_FRAME
  246. void NEAR _SET_PAGE(void) {
  247. #if USE_SEVERAL_PAGES
  248. __asm {
  249. PSHX ;// save X register
  250. __PIC_JSR(_GET_PAGE_REG)
  251. BEQ L_NOPAGE
  252. STAB 0,X ;// set page register
  253. L_NOPAGE:
  254. PULX ;// restore X register
  255. RTS
  256. }
  257. #else /* USE_SEVERAL_PAGES */
  258. __asm {
  259. STAB PAGE_ADDR ;// set page register
  260. RTS
  261. }
  262. #endif /* USE_SEVERAL_PAGES */
  263. }
  264. /*--------------------------- _LOAD_FAR_8 --------------------------------
  265. This runtime routine is used to access paged memory via a runtime function.
  266. It may also be used if the compiler option -Cp is not used with the runtime argument.
  267. Arguments :
  268. - offset part of an address in the Y register
  269. - page part of an address in the B register
  270. Result :
  271. - value to be read in the B register
  272. - all other registers remains unchanged
  273. - all page register still contain the same value
  274. --------------------------- _LOAD_FAR_8 ----------------------------------*/
  275. #ifdef __cplusplus
  276. extern "C"
  277. #endif
  278. #pragma NO_ENTRY
  279. #pragma NO_EXIT
  280. #pragma NO_FRAME
  281. void NEAR _LOAD_FAR_8(void) {
  282. #if USE_SEVERAL_PAGES
  283. __asm {
  284. PSHX ;// save X register
  285. __PIC_JSR(_GET_PAGE_REG)
  286. BEQ L_NOPAGE
  287. PSHA ;// save A register
  288. LDAA 0,X ;// save page register
  289. STAB 0,X ;// set page register
  290. LDAB 0,Y ;// actual load, overwrites page
  291. STAA 0,X ;// restore page register
  292. PULA ;// restore A register
  293. PULX ;// restore X register
  294. RTS
  295. L_NOPAGE:
  296. LDAB 0,Y ;// actual load, overwrites page
  297. PULX ;// restore X register
  298. RTS
  299. }
  300. #else /* USE_SEVERAL_PAGES */
  301. __asm {
  302. PSHA ;// save A register
  303. LDAA PAGE_ADDR ;// save page register
  304. STAB PAGE_ADDR ;// set page register
  305. LDAB 0,Y ;// actual load, overwrites page
  306. STAA PAGE_ADDR ;// restore page register
  307. PULA ;// restore A register
  308. RTS
  309. }
  310. #endif /* USE_SEVERAL_PAGES */
  311. }
  312. /*--------------------------- _LOAD_FAR_16 --------------------------------
  313. This runtime routine is used to access paged memory via a runtime function.
  314. It may also be used if the compiler option -Cp is not used with the runtime argument.
  315. Arguments :
  316. - offset part of an address in the Y register
  317. - page part of an address in the B register
  318. Result :
  319. - value to be read in the Y register
  320. - all other registers remains unchanged
  321. - all page register still contain the same value
  322. --------------------------- _LOAD_FAR_16 ----------------------------------*/
  323. #ifdef __cplusplus
  324. extern "C"
  325. #endif
  326. #pragma NO_ENTRY
  327. #pragma NO_EXIT
  328. #pragma NO_FRAME
  329. void NEAR _LOAD_FAR_16(void) {
  330. #if USE_SEVERAL_PAGES
  331. __asm {
  332. PSHX ;// save X register
  333. __PIC_JSR(_GET_PAGE_REG)
  334. BEQ L_NOPAGE
  335. PSHA ;// save A register
  336. LDAA 0,X ;// save page register
  337. STAB 0,X ;// set page register
  338. LDY 0,Y ;// actual load, overwrites address
  339. STAA 0,X ;// restore page register
  340. PULA ;// restore A register
  341. PULX ;// restore X register
  342. RTS
  343. L_NOPAGE:
  344. LDY 0,Y ;// actual load, overwrites address
  345. PULX ;// restore X register
  346. RTS
  347. }
  348. #else /* USE_SEVERAL_PAGES */
  349. __asm {
  350. PSHA ;// save A register
  351. LDAA PAGE_ADDR ;// save page register
  352. STAB PAGE_ADDR ;// set page register
  353. LDY 0,Y ;// actual load, overwrites address
  354. STAA PAGE_ADDR ;// restore page register
  355. PULA ;// restore A register
  356. RTS
  357. }
  358. #endif /* USE_SEVERAL_PAGES */
  359. }
  360. /*--------------------------- _LOAD_FAR_24 --------------------------------
  361. This runtime routine is used to access paged memory via a runtime function.
  362. It may also be used if the compiler option -Cp is not used with the runtime argument.
  363. Arguments :
  364. - offset part of an address in the Y register
  365. - page part of an address in the B register
  366. Result :
  367. - value to be read in the Y:B registers
  368. - all other registers remains unchanged
  369. - all page register still contain the same value
  370. --------------------------- _LOAD_FAR_24 ----------------------------------*/
  371. #ifdef __cplusplus
  372. extern "C"
  373. #endif
  374. #pragma NO_ENTRY
  375. #pragma NO_EXIT
  376. #pragma NO_FRAME
  377. void NEAR _LOAD_FAR_24(void) {
  378. #if USE_SEVERAL_PAGES
  379. __asm {
  380. PSHX ;// save X register
  381. __PIC_JSR(_GET_PAGE_REG)
  382. BEQ L_NOPAGE
  383. PSHA ;// save A register
  384. LDAA 0,X ;// save page register
  385. STAB 0,X ;// set page register
  386. LDAB 0,Y ;// actual load, overwrites page of address
  387. LDY 1,Y ;// actual load, overwrites offset of address
  388. STAA 0,X ;// restore page register
  389. PULA ;// restore A register
  390. PULX ;// restore X register
  391. RTS
  392. L_NOPAGE:
  393. LDAB 0,Y ;// actual load, overwrites page of address
  394. LDY 1,Y ;// actual load, overwrites offset of address
  395. PULX ;// restore X register
  396. RTS
  397. }
  398. #else /* USE_SEVERAL_PAGES */
  399. __asm {
  400. PSHA ;// save A register
  401. LDAA PAGE_ADDR ;// save page register
  402. STAB PAGE_ADDR ;// set page register
  403. LDAB 0,Y ;// actual load, overwrites page of address
  404. LDY 1,Y ;// actual load, overwrites offset of address
  405. STAA PAGE_ADDR ;// restore page register
  406. PULA ;// restore A register
  407. RTS
  408. }
  409. #endif /* USE_SEVERAL_PAGES */
  410. }
  411. /*--------------------------- _LOAD_FAR_32 --------------------------------
  412. This runtime routine is used to access paged memory via a runtime function.
  413. It may also be used if the compiler option -Cp is not used with the runtime argument.
  414. Arguments :
  415. - offset part of an address in the Y register
  416. - page part of an address in the B register
  417. Result :
  418. - low 16 bit of value to be read in the D registers
  419. - high 16 bit of value to be read in the Y registers
  420. - all other registers remains unchanged
  421. - all page register still contain the same value
  422. --------------------------- _LOAD_FAR_32 ----------------------------------*/
  423. #ifdef __cplusplus
  424. extern "C"
  425. #endif
  426. #pragma NO_ENTRY
  427. #pragma NO_EXIT
  428. #pragma NO_FRAME
  429. void NEAR _LOAD_FAR_32(void) {
  430. #if USE_SEVERAL_PAGES
  431. __asm {
  432. PSHX ;// save X register
  433. __PIC_JSR(_GET_PAGE_REG)
  434. BEQ L_NOPAGE
  435. LDAA 0,X ;// save page register
  436. PSHA ;// put it onto the stack
  437. STAB 0,X ;// set page register
  438. LDD 2,Y ;// actual load, low word
  439. LDY 0,Y ;// actual load, high word
  440. MOVB 1,SP+,0,X ;// restore page register
  441. PULX ;// restore X register
  442. RTS
  443. L_NOPAGE:
  444. LDD 2,Y ;// actual load, low word
  445. LDY 0,Y ;// actual load, high word
  446. PULX ;// restore X register
  447. RTS
  448. }
  449. #else /* USE_SEVERAL_PAGES */
  450. __asm {
  451. LDAA PAGE_ADDR ;// save page register
  452. PSHA ;// put it onto the stack
  453. STAB PAGE_ADDR ;// set page register
  454. LDD 2,Y ;// actual load, low word
  455. LDY 0,Y ;// actual load, high word
  456. MOVB 1,SP+,PAGE_ADDR ;// restore page register
  457. RTS
  458. }
  459. #endif /* USE_SEVERAL_PAGES */
  460. }
  461. /*--------------------------- _STORE_FAR_8 --------------------------------
  462. This runtime routine is used to access paged memory via a runtime function.
  463. It may also be used if the compiler option -Cp is not used with the runtime argument.
  464. Arguments :
  465. - offset part of an address in the Y register
  466. - page part of an address in the B register
  467. - value to be stored in the B register
  468. Result :
  469. - value stored at the address
  470. - all registers remains unchanged
  471. - all page register still contain the same value
  472. --------------------------- _STORE_FAR_8 ----------------------------------*/
  473. #ifdef __cplusplus
  474. extern "C"
  475. #endif
  476. #pragma NO_ENTRY
  477. #pragma NO_EXIT
  478. #pragma NO_FRAME
  479. void NEAR _STORE_FAR_8(void) {
  480. #if USE_SEVERAL_PAGES
  481. __asm {
  482. PSHX ;// save X register
  483. __PIC_JSR(_GET_PAGE_REG)
  484. BEQ L_NOPAGE
  485. PSHB ;// save B register
  486. LDAB 0,X ;// save page register
  487. MOVB 0,SP, 0,X ;// set page register
  488. STAA 0,Y ;// store the value passed in A
  489. STAB 0,X ;// restore page register
  490. PULB ;// restore B register
  491. PULX ;// restore X register
  492. RTS
  493. L_NOPAGE:
  494. STAA 0,Y ;// store the value passed in A
  495. PULX ;// restore X register
  496. RTS
  497. }
  498. #else /* USE_SEVERAL_PAGES */
  499. __asm {
  500. PSHB ;// save A register
  501. LDAB PAGE_ADDR ;// save page register
  502. MOVB 0,SP,PAGE_ADDR ;// set page register
  503. STAA 0,Y ;// store the value passed in A
  504. STAB PAGE_ADDR ;// restore page register
  505. PULB ;// restore B register
  506. RTS
  507. }
  508. #endif /* USE_SEVERAL_PAGES */
  509. }
  510. /*--------------------------- _STORE_FAR_16 --------------------------------
  511. This runtime routine is used to access paged memory via a runtime function.
  512. It may also be used if the compiler option -Cp is not used with the runtime argument.
  513. Arguments :
  514. - offset part of an address in the Y register
  515. - page part of an address in the B register
  516. - value to be stored in the X register
  517. Result :
  518. - value stored at the address
  519. - all registers remains unchanged
  520. - all page register still contain the same value
  521. --------------------------- _STORE_FAR_16 ----------------------------------*/
  522. #ifdef __cplusplus
  523. extern "C"
  524. #endif
  525. #pragma NO_ENTRY
  526. #pragma NO_EXIT
  527. #pragma NO_FRAME
  528. void NEAR _STORE_FAR_16(void) {
  529. #if USE_SEVERAL_PAGES
  530. __asm {
  531. PSHX ;// save X register
  532. __PIC_JSR(_GET_PAGE_REG)
  533. BEQ L_NOPAGE
  534. PSHA
  535. LDAA 0,X ;// save page register
  536. STAB 0,X ;// set page register
  537. MOVW 1,SP,0,Y ;// store the value passed in X
  538. STAA 0,X ;// restore page register
  539. PULA ;// restore A register
  540. PULX ;// restore X register
  541. RTS
  542. L_NOPAGE:
  543. STX 0,Y ;// store the value passed in X
  544. PULX ;// restore X register
  545. RTS
  546. }
  547. #else /* USE_SEVERAL_PAGES */
  548. __asm {
  549. PSHA ;// save A register
  550. LDAA PAGE_ADDR ;// save page register
  551. STAB PAGE_ADDR ;// set page register
  552. STX 0,Y ;// store the value passed in X
  553. STAA PAGE_ADDR ;// restore page register
  554. PULA ;// restore A register
  555. RTS
  556. }
  557. #endif /* USE_SEVERAL_PAGES */
  558. }
  559. /*--------------------------- _STORE_FAR_24 --------------------------------
  560. This runtime routine is used to access paged memory via a runtime function.
  561. It may also be used if the compiler option -Cp is not used with the runtime argument.
  562. Arguments :
  563. - offset part of an address in the Y register
  564. - page part of an address in the B register
  565. - value to be stored in the X:A registers (X : low 16 bit, A : high 8 bit)
  566. Result :
  567. - value stored at the address
  568. - all registers remains unchanged
  569. - all page register still contain the same value
  570. --------------------------- _STORE_FAR_24 ----------------------------------*/
  571. #ifdef __cplusplus
  572. extern "C"
  573. #endif
  574. #pragma NO_ENTRY
  575. #pragma NO_EXIT
  576. #pragma NO_FRAME
  577. void NEAR _STORE_FAR_24(void) {
  578. #if USE_SEVERAL_PAGES
  579. __asm {
  580. PSHX ;// save X register
  581. __PIC_JSR(_GET_PAGE_REG)
  582. BEQ L_NOPAGE
  583. PSHA
  584. LDAA 0,X ;// save page register
  585. STAB 0,X ;// set page register
  586. MOVW 1,SP, 1,Y ;// store the value passed in X
  587. MOVB 0,SP, 0,Y ;// store the value passed in A
  588. STAA 0,X ;// restore page register
  589. PULA ;// restore A register
  590. PULX ;// restore X register
  591. RTS
  592. L_NOPAGE:
  593. STX 1,Y ;// store the value passed in X
  594. STAA 0,Y ;// store the value passed in X
  595. PULX ;// restore X register
  596. RTS
  597. }
  598. #else /* USE_SEVERAL_PAGES */
  599. __asm {
  600. PSHA ;// save A register
  601. LDAA PAGE_ADDR ;// save page register
  602. STAB PAGE_ADDR ;// set page register
  603. MOVB 0,SP, 0,Y ;// store the value passed in A
  604. STX 1,Y ;// store the value passed in X
  605. STAA PAGE_ADDR ;// restore page register
  606. PULA ;// restore A register
  607. RTS
  608. }
  609. #endif /* USE_SEVERAL_PAGES */
  610. }
  611. /*--------------------------- _STORE_FAR_32 --------------------------------
  612. This runtime routine is used to access paged memory via a runtime function.
  613. It may also be used if the compiler option -Cp is not used with the runtime argument.
  614. Arguments :
  615. - offset part of an address in the Y register
  616. - page part of an address is on the stack at 3,SP (just below the return address)
  617. - value to be stored in the X:D registers (D : low 16 bit, X : high 16 bit)
  618. Result :
  619. - value stored at the address
  620. - all registers remains unchanged
  621. - the page part is removed from the stack
  622. - all page register still contain the same value
  623. --------------------------- _STORE_FAR_32 ----------------------------------*/
  624. #ifdef __cplusplus
  625. extern "C"
  626. #endif
  627. #pragma NO_ENTRY
  628. #pragma NO_EXIT
  629. #pragma NO_FRAME
  630. void NEAR _STORE_FAR_32(void) {
  631. #if USE_SEVERAL_PAGES
  632. __asm {
  633. PSHX ;// save X register
  634. __PIC_JSR(_GET_PAGE_REG)
  635. BEQ L_NOPAGE
  636. PSHD
  637. LDAA 0,X ;// save page register
  638. MOVB 6,SP, 0,X ;// set page register
  639. MOVW 2,SP, 0,Y ;// store the value passed in X (high word)
  640. MOVW 0,SP, 2,Y ;// store the value passed in D (low word)
  641. STAA 0,X ;// restore page register
  642. PULD ;// restore A register
  643. BRA done
  644. L_NOPAGE:
  645. MOVW 0,SP, 0,Y ;// store the value passed in X (high word)
  646. STD 2,Y ;// store the value passed in D (low word)
  647. done:
  648. PULX ;// restore X register
  649. MOVW 0,SP, 1,+SP ;// move return address
  650. RTS
  651. }
  652. #else /* USE_SEVERAL_PAGES */
  653. __asm {
  654. PSHD ;// save D register
  655. LDAA PAGE_ADDR ;// save page register
  656. LDAB 4,SP ;// load page part of address
  657. STAB PAGE_ADDR ;// set page register
  658. STX 0,Y ;// store the value passed in X
  659. MOVW 0,SP, 2,Y ;// store the value passed in D (low word)
  660. STAA PAGE_ADDR ;// restore page register
  661. PULD ;// restore D register
  662. MOVW 0,SP, 1,+SP ;// move return address
  663. RTS
  664. }
  665. #endif /* USE_SEVERAL_PAGES */
  666. }
  667. /*--------------------------- _FAR_COPY_RC --------------------------------
  668. This runtime routine is used to access paged memory via a runtime function.
  669. It may also be used if the compiler option -Cp is not used with the runtime argument.
  670. Arguments :
  671. - offset part of the source int the X register
  672. - page part of the source in the A register
  673. - offset part of the dest int the Y register
  674. - page part of the dest in the B register
  675. - number of bytes to be copied is defined by the next 2 bytes after the return address.
  676. Result :
  677. - memory area copied
  678. - no registers are saved, i.e. all registers may be destroyed
  679. - all page register still contain the same value as before the call
  680. - the function returns after the constant defining the number of bytes to be copied
  681. stack-structure at the loop-label:
  682. 0,SP : destination offset
  683. 2,SP : source page
  684. 3,SP : destination page
  685. 4,SP : source offset
  686. 6,SP : points to length to be copied. This function returns after the size
  687. A usual call to this function looks like:
  688. struct Huge src, dest;
  689. ; ...
  690. LDX #src
  691. LDAA #PAGE(src)
  692. LDY #dest
  693. LDAB #PAGE(dest)
  694. JSR _FAR_COPY_RC
  695. DC.W sizeof(struct Huge)
  696. ; ...
  697. --------------------------- _FAR_COPY_RC ----------------------------------*/
  698. #ifdef __cplusplus
  699. extern "C"
  700. #endif
  701. #pragma NO_ENTRY
  702. #pragma NO_EXIT
  703. #pragma NO_FRAME
  704. void NEAR _FAR_COPY_RC(void) {
  705. #if USE_SEVERAL_PAGES
  706. __asm {
  707. DEX ;// source addr-=1, because loop counter ends at 1
  708. PSHX ;// save source offset
  709. PSHD ;// save both pages
  710. DEY ;// destination addr-=1, because loop counter ends at 1
  711. PSHY ;// save destination offset
  712. LDY 6,SP ;// Load Return address
  713. LDX 2,Y+ ;// Load Size to copy
  714. STY 6,SP ;// Store adjusted return address
  715. loop:
  716. LDD 4,SP ;// load source offset
  717. LEAY D,X ;// calculate actual source address
  718. LDAB 2,SP ;// load source page
  719. __PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
  720. PSHB ;// save value
  721. LDD 0+1,SP ;// load destination offset
  722. LEAY D,X ;// calculate actual destination address
  723. PULA ;// restore value
  724. LDAB 3,SP ;// load destination page
  725. __PIC_JSR(_STORE_FAR_8) ;// store one byte
  726. DEX
  727. BNE loop
  728. LEAS 6,SP ;// release stack
  729. _SRET ;// debug info only: This is the last instr of a function with a special return
  730. RTS ;// return
  731. }
  732. #else
  733. __asm {
  734. PSHD ;// store page registers
  735. TFR X,D
  736. PSHY ;// temporary space
  737. LDY 4,SP ;// load return address
  738. ADDD 2,Y+ ;// calculate source end address. Increment return address
  739. STY 4,SP
  740. PULY
  741. PSHD ;// store src end address
  742. LDAB 2,SP ;// reload source page
  743. LDAA PAGE_ADDR ;// save page register
  744. PSHA
  745. loop:
  746. STAB PAGE_ADDR ;// set source page
  747. LDAA 1,X+ ;// load value
  748. MOVB 4,SP, PAGE_ADDR ;// set destination page
  749. STAA 1,Y+
  750. CPX 1,SP
  751. BNE loop
  752. LDAA 5,SP+ ;// restore old page value and release stack
  753. STAA PAGE_ADDR ;// store it into page register
  754. _SRET ;// debug info only: This is the last instr of a function with a special return
  755. RTS
  756. }
  757. #endif
  758. }
  759. /*--------------------------- _FAR_COPY --------------------------------
  760. The _FAR_COPY runtime routine was used to copied large memory blocks in previous compiler releases.
  761. However this release now does use _FAR_COPY_RC instead. The only difference is how the size of
  762. the area to be copied is passed into the function. For _FAR_COPY the size is passed on the stack just
  763. above the return address. _FAR_COPY_RC does expect the return address just after the JSR _FAR_COPY_RC call
  764. in the code of the caller. This allows for denser code calling _FAR_COPY_RC but does also need a slightly
  765. larger runtime routine and it is slightly slower.
  766. The _FAR_COPY routine is here now mainly for compatibility with previous releases.
  767. The current compiler does not use it.
  768. --------------------------- _FAR_COPY ----------------------------------*/
  769. #ifdef __cplusplus
  770. extern "C"
  771. #endif
  772. #pragma NO_ENTRY
  773. #pragma NO_EXIT
  774. #pragma NO_FRAME
  775. void NEAR _FAR_COPY(void) {
  776. #if USE_SEVERAL_PAGES
  777. __asm {
  778. DEX ;// source addr-=1, because loop counter ends at 1
  779. PSHX ;// save source offset
  780. PSHD ;// save both pages
  781. DEY ;// destination addr-=1, because loop counter ends at 1
  782. PSHY ;// save destination offset
  783. LDX 8,SP ;// load counter, assuming counter > 0
  784. loop:
  785. LDD 4,SP ;// load source offset
  786. LEAY D,X ;// calculate actual source address
  787. LDAB 2,SP ;// load source page
  788. __PIC_JSR(_LOAD_FAR_8) ;// load 1 source byte
  789. PSHB ;// save value
  790. LDD 0+1,SP ;// load destination offset
  791. LEAY D,X ;// calculate actual destination address
  792. PULA ;// restore value
  793. LDAB 3,SP ;// load destination page
  794. __PIC_JSR(_STORE_FAR_8) ;// store one byte
  795. DEX
  796. BNE loop
  797. LDX 6,SP ;// load return address
  798. LEAS 10,SP ;// release stack
  799. JMP 0,X ;// return
  800. }
  801. #else
  802. __asm {
  803. PSHD ;// store page registers
  804. TFR X,D
  805. ADDD 4,SP ;// calculate source end address
  806. STD 4,SP
  807. PULB ;// reload source page
  808. LDAA PAGE_ADDR ;// save page register
  809. PSHA
  810. loop:
  811. STAB PAGE_ADDR ;// set source page
  812. LDAA 1,X+ ;// load value
  813. MOVB 1,SP, PAGE_ADDR ;// set destination page
  814. STAA 1,Y+
  815. CPX 4,SP
  816. BNE loop
  817. LDAA 2,SP+ ;// restore old page value and release stack
  818. STAA PAGE_ADDR ;// store it into page register
  819. LDX 4,SP+ ;// release stack and load return address
  820. JMP 0,X ;// return
  821. }
  822. #endif
  823. }
  824. #else /* __HCS12X__ */
  825. /*
  826. The HCS12X knows two different kind of addresses:
  827. - Logical addresses. E.g.
  828. MOVB #page(var),RPAGE
  829. INC var
  830. - Global addresses E.g.
  831. MOVB #page(var),GPAGE
  832. GLDAA var
  833. INCA
  834. GSTAA var
  835. Global addresses are used with G-Load's and G-Store's, logical addresses are used for all the other instructions
  836. and occasions. As HC12's or HCS12's do not have the G-Load and G-Store instructions,
  837. global addresses are not used with these processor families.
  838. They are only used with HCS12X chips (and maybe future ones deriving from a HCS12X).
  839. Logical and Global addresses can point to the same object, however the global and logical address of an object
  840. are different for most objects (actually for all except the registers from 0 to 0x7FF).
  841. Therefore the compiler needs to transform in between them.
  842. HCS12X Pointer types:
  843. The following are logical addresses:
  844. - all 16 bit pointers
  845. - "char* __near": always.
  846. - "char *" in the small and banked memory model
  847. - 24 bit dpage, epage, ppage or rpage pointers (*1) (note: the first HCS12X compilers may not support these pointer types)
  848. - "char *__dpage": Note this type only exists for
  849. orthogonality with the HC12 A4 chip which has a DPAGE reg.
  850. It does not apply to the HCS12X.
  851. - "char *__epage": 24 bit pointer using the EPAGE register
  852. - "char *__ppage": 24 bit pointer using the PPAGE register.
  853. As the PPAGE is also used for BANKED code,
  854. using this pointer type is only legal from non banked code.
  855. - "char *__rpage": 24 bit pointer using the RPAGE register
  856. The following are global addresses:
  857. "char*": in the large memory model (only HCS12X)
  858. "char* __far": always for HCS12X.
  859. (*1): For the HC12 and HCS12 "char* __far" and "char*" in the large memory model are also logical.
  860. Some notes for the HC12/HCS12 programmers.
  861. 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.
  862. For the HC12, a far address is using the logical addresses, for the HCS12X however, far addresses are using global addresses.
  863. This does cause troubles for the unaware!
  864. The conversion routines implemented in this file support the special HCS12XE RAM mapping (when RAMHM is set).
  865. To enable this mapping compile this file with the "-MapRAM" compiler option.
  866. HCS12X Logical Memory map
  867. Logical Addresses Used for shadowed at page register Global Address
  868. 0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
  869. 0x??0800 .. 0x??0BFF Paged EEPROM EPAGE (@0x17) 0x100000+EPAGE*0x0400
  870. 0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
  871. 0x??1000 .. 0x??1FFF Paged RAM RPAGE (@0x16) 0x000000+RPAGE*0x1000
  872. 0x002000 .. 0x003FFF Non Paged RAM 0xFE1000..0xFF1FFF Not Paged 0x0FE000
  873. 0x004000 .. 0x007FFF Non Paged FLASH 0xFC8000..0xFCBFFF Not Paged 0x7F4000
  874. 0x??8000 .. 0x00BFFF Paged FLASH PPAGE (@0x30) 0x400000+PPAGE*0x4000
  875. 0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
  876. NA: Not Applicable
  877. HCS12X Global Memory map
  878. Global Addresses Used for Logical mapped at
  879. 0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
  880. 0x000800 .. 0x000FFF DMA registers Not mapped
  881. 0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
  882. 0x0FE000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x003FFF
  883. 0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
  884. 0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
  885. 0x140000 .. 0x3FFFFF External Space Not mapped
  886. 0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
  887. 0x7F4000 .. 0x7F7FFF FLASH, Log non paged 0x004000 .. 0x007FFF
  888. 0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
  889. HCS12XE Logical Memory map (with RAMHM set)
  890. Logical Addresses Used for shadowed at page register Global Address
  891. 0x000000 .. 0x0007FF Peripheral Registers Not Paged 0x000000
  892. 0x??0800 .. 0x??0BFF Paged EEPROM EPAGE 0x100000+EPAGE*0x0400
  893. 0x000C00 .. 0x000FFF Non Paged EEPROM 0xFF0800..0xFF0FFF Not Paged 0x13FC00
  894. 0x??1000 .. 0x??1FFF Paged RAM RPAGE 0x000000+RPAGE*0x1000
  895. 0x002000 .. 0x003FFF Non Paged RAM 0xFA1000..0xFB1FFF Not Paged 0x0FA000
  896. 0x004000 .. 0x007FFF Non Paged RAM 0xFC1000..0xFF1FFF Not Paged 0x0FC000
  897. 0x??8000 .. 0x00BFFF Paged FLASH PPAGE 0x400000+PPAGE*0x4000
  898. 0x00C000 .. 0x00FFFF Non Paged FLASH 0xFF8000..0xFFBFFF Not Paged 0x7FC000
  899. NA: Not Applicable
  900. HCS12X Global Memory map (with RAMHM set)
  901. Global Addresses Used for Logical mapped at
  902. 0x000000 .. 0x0007FF Peripheral Registers 0x000000 .. 0x0007FF
  903. 0x000800 .. 0x000FFF DMA registers Not mapped
  904. 0x001000 .. 0x0FFFFF RAM 0x??1000 .. 0x??1FFF
  905. 0x0FA000 .. 0x0FFFFF RAM, Log non paged 0x002000 .. 0x007FFF
  906. 0x100000 .. 0x13FFFF EEPROM 0x??0800 .. 0x??0BFF
  907. 0x13FC00 .. 0x13FFFF EEPROM non paged 0x000C00 .. 0x000FFF
  908. 0x140000 .. 0x3FFFFF External Space Not mapped
  909. 0x400000 .. 0x7FFFFF FLASH 0x??8000 .. 0x??BFFF
  910. 0x7F4000 .. 0x7F7FFF FLASH, Log non paged Not mapped
  911. 0x7FC000 .. 0x7FFFFF FLASH, Log non paged 0x00C000 .. 0x00FFFF
  912. How to read this table:
  913. For logical addresses, the lower 16 bits of the address do determine in which area the address is,
  914. if this address is paged, then this entry also controls and which of the EPAGE, PPAGE or RPAGE
  915. page register is controlling the bits 16 to 23 of the address.
  916. For global addresses, the bits 16 to 23 have to be in the GPAGE register and the lower 16 bits
  917. have to be used with the special G load or store instructions (e.g. GLDAA).
  918. As example the logical address 0x123456 is invalid. Because its lower bits 0x3456 are in a
  919. non paged area, so the page 0x12 does not exist.
  920. The address 0xFE1020 however does exist. To access it, the RPAGE has to contain 0xFE and the
  921. offset 0x1020 has to be used.
  922. ORG $7000
  923. MOVB #0xFE, 0x16 ; RPAGE
  924. LDAA 0x1020 ; reads at the logical address 0xFE1020
  925. Because the last two RAM pages are also accessible directly from 0x2000 to 0x3FFF, the
  926. following shorter code does read the same memory location:
  927. ORG $7000
  928. LDAA 0x2020 ; reads at the logical address 0x2020
  929. ; which maps to the same memory as 0xFE1020
  930. This memory location also has a global address. For logical 0xFE1020 the global address is 0x0FE020.
  931. So the following code does once more access the same memory location:
  932. ORG $7000
  933. MOVB #0x0F, 0x10 ; GPAGE
  934. GLDAA 0xE020 ; reads at the global address 0x0FE020
  935. ; which maps to the same memory as the logical addr. 0xFE1020
  936. Therefore every memory location for the HCS12X has up to 3 different addresses.
  937. Up to two logical and one global.
  938. Notes.
  939. - Not every address has a logical equivalent. The external space is only available in the global address space.
  940. - The PPAGE must only be set if the code is outside of the 0x8000 to 0xBFFF range.
  941. If not, the next code fetch will be from the new wrong PPAGE value.
  942. - Inside of the paged area, the highest pages are allocated first. So all HCS12X's do have the FF pages
  943. (if they have this memory type at all).
  944. - For RPAGE, the value 0 is illegal. Otherwise the global addresses would overlap with the registers.
  945. */
  946. #if __OPTION_ACTIVE__("-MapRAM")
  947. #define __HCS12XE_RAMHM_SET__
  948. #endif
  949. /*--------------------------- pointer conversion operations -------------------------------*/
  950. /*--------------------------- _CONV_GLOBAL_TO_LOGICAL --------------------------------
  951. Convert 24 bit logical to 24 bit global pointer
  952. ("char*__far" to "char*__gpage")
  953. Arguments :
  954. - B : page part of global address
  955. - X : 16 offset part of global address
  956. Postcondition :
  957. - B == page of returned logical address
  958. - X == offset of returned logical address
  959. - Y remains unchanged
  960. - A remains unchanged
  961. */
  962. /*--------------------------- Convert 24 bit global to 24 bit logical pointer ----------------------------------*/
  963. /* B:X = Logical(B:X) */
  964. #ifdef __cplusplus
  965. extern "C"
  966. #endif
  967. #pragma NO_FRAME
  968. #pragma NO_ENTRY
  969. #pragma NO_EXIT
  970. void NEAR _CONV_GLOBAL_TO_LOGICAL(void) {
  971. __asm {
  972. CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
  973. BLO Below400000
  974. // from 0x400000 to 0x7FFFFF
  975. CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
  976. BNE PAGED_FLASH_AREA
  977. #ifndef __HCS12XE_RAMHM_SET__
  978. BITX #0x4000
  979. BEQ PAGED_FLASH_AREA
  980. #else
  981. CPX #0xC000
  982. BLO PAGED_FLASH_AREA
  983. #endif
  984. // from 0x7F4000 to 0x7F7FFF or 0x7FC000 to 0x7FFFFF
  985. ;// Note: offset in X is already OK.
  986. CLRB ;// logical page == 0
  987. RTS
  988. PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
  989. // from 0x400000 to 0x7F3FFF or 0x7F8000 to 0x7FBFFF
  990. LSLX ; // shift 24 bit address 2 bits to the left to get correct page in B
  991. ROLB
  992. LSLX
  993. ROLB
  994. LSRX ; // shift back to get offset from 0x8000 to 0xBFFF
  995. SEC
  996. RORX
  997. RTS ;// done
  998. Below400000:
  999. // from 0x000000 to 0x3FFFFF
  1000. #if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
  1001. CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
  1002. BLO Below140000
  1003. ERROR !!!! ;// this mapping is not possible! What should we do?
  1004. RTS
  1005. Below140000:
  1006. // from 0x000000 to 0x13FFFF
  1007. #endif
  1008. CMPB #0x10 ;// if >= 0x100000 it's EEPROM
  1009. BLO Below100000
  1010. // from 0x100000 to 0x13FFFF (or 0x3FFFFF)
  1011. CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
  1012. BLO Below13FC00
  1013. CPX #0xFC00
  1014. BLO Below13FC00
  1015. // from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
  1016. LEAX 0x1000,X ;// same as SUBX #0xF000 // map from 0xFC00 to 0x0C00
  1017. CLRB
  1018. RTS
  1019. Below13FC00:
  1020. // from 0x100000 to 0x13FBFF
  1021. PSHA
  1022. TFR XH,A ;// calculate logical page
  1023. EXG A,B
  1024. LSRD
  1025. LSRD
  1026. PULA
  1027. ANDX #0x03FF
  1028. LEAX 0x0800,X ;// same as ORX #0x0800
  1029. RTS
  1030. Below100000:
  1031. // from 0x000000 to 0x0FFFFF
  1032. TSTB
  1033. BNE RAM_AREA
  1034. CPX #0x1000
  1035. BLO Below001000
  1036. RAM_AREA:
  1037. // from 0x001000 to 0x0FFFFF
  1038. CMPB #0x0F
  1039. BNE PagedRAM_AREA
  1040. #ifndef __HCS12XE_RAMHM_SET__
  1041. CPX #0xE000
  1042. BLO PagedRAM_AREA
  1043. // from 0x0FE000 to 0x0FFFFF
  1044. SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
  1045. #else
  1046. CPX #0xA000
  1047. BLO PagedRAM_AREA
  1048. // from 0x0FA000 to 0x0FFFFF
  1049. SUBX #(0xA000-0x2000) ;// map 0xA000 to 0x2000
  1050. #endif
  1051. CLRB ;// Page is 0
  1052. RTS
  1053. PagedRAM_AREA:
  1054. // from 0x001000 to 0x0FDFFF
  1055. PSHA
  1056. TFR XH, A ;// calculate logical page
  1057. EXG A,B
  1058. LSRD
  1059. LSRD
  1060. LSRD
  1061. LSRD
  1062. PULA
  1063. ANDX #0x0FFF
  1064. LEAX 0x1000,X ;// same as ORX #0x1000
  1065. RTS
  1066. Below001000:
  1067. // from 0x000000 to 0x000FFF
  1068. #if 0
  1069. CMPA #0x08
  1070. BLO Below000800
  1071. // from 0x000800 to 0x000FFF
  1072. // ??? DMA Regs?
  1073. RTS
  1074. Below000800:
  1075. // from 0x000000 to 0x0007FF
  1076. #endif
  1077. CLRB
  1078. RTS
  1079. }
  1080. }
  1081. /*--------------------------- _CONV_GLOBAL_TO_NEAR --------------------------------
  1082. Convert 24 bit global to 16 bit logical pointer
  1083. ("char*__far" to "char*")
  1084. Arguments :
  1085. - B : page part of global address
  1086. - X : 16 offset part of global address
  1087. Postcondition :
  1088. - B is undefined
  1089. - A remains unchanged
  1090. - X == offset of returned logical address
  1091. - Y remains unchanged
  1092. */
  1093. /*--------------------------- Convert 24 bit global to 16 bit logical pointer ----------------------------------*/
  1094. /* X = Logical(B:X) */
  1095. #ifdef __cplusplus
  1096. extern "C"
  1097. #endif
  1098. #define _REUSE_CONV_GLOBAL_TO_LOGICAL 1
  1099. #pragma NO_FRAME
  1100. #pragma NO_ENTRY
  1101. #pragma NO_EXIT
  1102. void NEAR _CONV_GLOBAL_TO_NEAR(void){
  1103. #if _REUSE_CONV_GLOBAL_TO_LOGICAL /* do we want an optimized version? */
  1104. __asm JMP _CONV_GLOBAL_TO_LOGICAL; /* offset for NEAR is same as for LOGICAL. */
  1105. #else
  1106. __asm {
  1107. CMPB #0x40 ;// flash (0x400000..0x7FFFFF) or not?
  1108. BLO Below400000
  1109. // from 0x400000 to 0x7FFFFF
  1110. #ifndef __HCS12XE_RAMHM_SET__
  1111. CMPB #0x7F ;// check for Unpaged areas 0x7FC000..0x7FFFFF and 0x7F4000..0x7F7FFF
  1112. BNE PAGED_FLASH_AREA
  1113. CPX #0x4000
  1114. BLO PAGED_FLASH_AREA
  1115. // from 0x7F4000 to 0x7FFFFF
  1116. #else
  1117. CMPB #0x7F ;// check for Unpaged area 0x7FC000..0x7FFFFF
  1118. BNE PAGED_FLASH_AREA
  1119. CPX #0xC000
  1120. BLO PAGED_FLASH_AREA
  1121. // from 0x7FC000 to 0x7FFFFF
  1122. #endif
  1123. ;// note non PAGED flash areas or paged area 0x7F8000..0x7FBFFF which are mapping all correctly
  1124. RTS
  1125. PAGED_FLASH_AREA: ;// paged flash. Map to 0x8000..0xBFFF
  1126. // from 0x400000 to 0x7F3FFF
  1127. ANDX #0x3F00 ;// cut to 0.. 0x3FFF
  1128. LEAX 0x8000,X ;// same as ORX #0x8000 ;// move to 0x8000..0xBFFF
  1129. RTS ;// done
  1130. Below400000:
  1131. // from 0x000000 to 0x3FFFFF
  1132. #if 0 /* How should we handle mapping to External Space. There is no logical equivalent. This is an error case! */
  1133. CMPB #0x14 ;// check if above 0x140000. If so, its in the external space
  1134. BLO Below140000
  1135. ERROR !!!! ;// this mapping is not possible! What should we do?
  1136. RTS
  1137. Below140000:
  1138. // from 0x000000 to 0x13FFFF
  1139. #endif
  1140. CMPB #0x10 ;// if >= 0x100000 it's EEPROM
  1141. BLO Below100000
  1142. // from 0x100000 to 0x13FFFF (or 0x3FFFFF)
  1143. CMPB #0x13 ;// check if its is in the non paged EEPROM area at 0x13FC00..0x13FFFF
  1144. BNE Below13FC00
  1145. CPX #0xFC00
  1146. BLO Below13FC00
  1147. // from 0x13FC00 to 0x13FFFF (or 0x3FFFFF)
  1148. SUBX #0xF000 ;// map from 0xFC00 to 0x0C00
  1149. RTS
  1150. Below13FC00:
  1151. // from 0x100000 to 0x13FBFF
  1152. ANDX #0x03FF
  1153. LEAX 0x800,X ;// same as ORX #0x0800
  1154. RTS
  1155. Below100000:
  1156. // from 0x000000 to 0x0FFFFF
  1157. TBNE B,RAM_AREA
  1158. CPX #0x1000
  1159. BLO Below001000
  1160. RAM_AREA:
  1161. // from 0x001000 to 0x0FFFFF
  1162. CMPB #0x0F
  1163. BNE PagedRAM_AREA
  1164. #ifndef __HCS12XE_RAMHM_SET__
  1165. CPX #0xE000
  1166. BLO PagedRAM_AREA
  1167. // from 0x0FE000 to 0x0FFFFF
  1168. SUBX #(0xE000-0x2000) ;// map 0xE000 to 0x2000
  1169. #else
  1170. CPX #0xA000
  1171. BLO PagedRAM_AREA
  1172. // from 0x0FA000 to 0x0FFFFF
  1173. SUBX #(0xA000-0x2000) ;// map 0xA000 to 0x2000
  1174. #endif
  1175. RTS
  1176. PagedRAM_AREA:
  1177. // from 0x001000 to 0x0FDFFF (0x001000 to 0x0F9FFF if HCS12XE RAM mapping is enabled)
  1178. ANDX #0x0FFF
  1179. LEAX 0x1000,X ;// same as ORX #0x1000
  1180. RTS
  1181. Below001000:
  1182. // from 0x000000 to 0x000FFF
  1183. RTS
  1184. }
  1185. #endif
  1186. }
  1187. /*--------------------------- _CONV_NEAR_TO_GLOBAL --------------------------------
  1188. Convert 16 bit logical to 24 bit global pointer
  1189. ("char*__near" to "char*__far")
  1190. Arguments :
  1191. - X : 16 bit near pointer
  1192. Postcondition :
  1193. - B == page of returned global address
  1194. - X == offset of returned global address
  1195. - Y remains unchanged
  1196. - A is unspecified
  1197. */
  1198. /*--------------------------- Convert 16 bit logical to 24 bit global pointer ----------------------------------*/
  1199. /* B:X = Global(X) */
  1200. #ifdef __cplusplus
  1201. extern "C"
  1202. #endif
  1203. #pragma NO_FRAME
  1204. #pragma NO_ENTRY
  1205. #pragma NO_EXIT
  1206. void NEAR _CONV_NEAR_TO_GLOBAL(void){
  1207. __asm {
  1208. // syntax:
  1209. // input 16 bit offset is bit15..bit0
  1210. // ppage values: ppage7..ppage0
  1211. // epage values: epage7..epage0
  1212. // dpage values: dpage7..dpage0
  1213. // rpage values: rpage7..rpage0
  1214. PSHX ;// D contains bit15..bit0
  1215. TFR X,D ;// D is cheaper to shift
  1216. LSLD ;// D contains 0 bit14..bit0, C contains bit15
  1217. BCC Below8000 ;// bit15 == 0?
  1218. // from 0x8000 to 0xFFFF
  1219. LSLD ;// D contains 00 bit13..bit0, C contains bit14
  1220. BCC BelowC000
  1221. LDAB #0x7F
  1222. PULX
  1223. RTS ;// returns 0b0111 1111 11 bit13...bit0
  1224. BelowC000: ;// from 0x8000 to 0xBFFF
  1225. TFR D,X
  1226. LDAB __PPAGE_ADR__
  1227. SEC
  1228. RORB
  1229. RORX
  1230. LSRB
  1231. RORX
  1232. LEAS 2,SP
  1233. RTS ;// returns 0b01 ppage7..ppage0 bit13...bit0
  1234. Below8000:
  1235. LSLD ;// D contains 00 bit13..bit0, C contains bit14
  1236. BCC Below4000
  1237. // from 0x4000 to 0x7FFF
  1238. PULX
  1239. #ifndef __HCS12XE_RAMHM_SET__
  1240. LDAB #0x7F
  1241. #else
  1242. LEAX (0xC000-0x4000),X
  1243. LDAB #0x0F
  1244. #endif
  1245. RTS ;// returns 0b0111 1111 01 bit13...bit0
  1246. Below4000:
  1247. LSLD ;// D contains 000 bit12..bit0, C contains bit13
  1248. BCC Below2000
  1249. // from 0x2000 to 0x3FFF
  1250. PULX
  1251. #ifndef __HCS12XE_RAMHM_SET__
  1252. LEAX (0xE000-0x2000),X
  1253. #else
  1254. LEAX (0xA000-0x2000),X
  1255. #endif
  1256. LDAB #0x0F
  1257. RTS ;// returns 0b0000 1111 111 bit12...bit0
  1258. Below2000:
  1259. LSLD ;// D contains 0000 bit11..bit0, C contains bit12
  1260. BCC Below1000
  1261. // from 0x1000 to 0x1FFF
  1262. LDAB __RPAGE_ADR__
  1263. LDAA #0x10
  1264. MUL
  1265. EORB 0,SP
  1266. EORB #0x10 ;// clear 1 bit
  1267. STAB 0,SP
  1268. TFR A,B
  1269. PULX
  1270. RTS
  1271. Below1000:
  1272. LSLD ;// D contains 0000 0 bit10..bit0, C contains bit11
  1273. BCC Below0800
  1274. // from 0x0800 to 0x0FFF
  1275. LSLD ;// D contains 0000 00 bit9..bit0, C contains bit10
  1276. BCC Below0C00
  1277. // from 0x0C00 to 0x0FFF
  1278. LDAB #0x13
  1279. PULX
  1280. LEAX 0xF000,X
  1281. RTS ;// returns 0b0001 0011 1111 11 bit9...bit0
  1282. Below0C00:
  1283. // from 0x0800 to 0x0BFF
  1284. LDAB __EPAGE_ADR__
  1285. LDAA #0x04
  1286. MUL
  1287. EORB 0,SP
  1288. EORB #0x08
  1289. STAB 0,SP
  1290. TFR A,B
  1291. ORAB #0b00010000
  1292. PULX
  1293. RTS
  1294. Below0800:
  1295. PULX
  1296. CLRB
  1297. RTS
  1298. }
  1299. }
  1300. /*--------------------------- _CONV_STACK_NEAR_TO_GLOBAL --------------------------------
  1301. Convert 16 bit logical of address on the stack 24 bit global pointer
  1302. ("char*__near" to "char*__far")
  1303. Arguments :
  1304. - X : 16 bit near pointer
  1305. Postcondition :
  1306. - B == page of returned global address
  1307. - X == offset of returned global address
  1308. - Y remains unchanged
  1309. - A is unspecified
  1310. */
  1311. /*--------------------------- Convert 16 bit logical stack address to 24 bit global pointer ----------------------------------*/
  1312. /* B:X = Global(D) */
  1313. #ifdef __cplusplus
  1314. extern "C"
  1315. #endif
  1316. #pragma NO_FRAME
  1317. #pragma NO_ENTRY
  1318. #pragma NO_EXIT
  1319. void NEAR _CONV_STACK_NEAR_TO_GLOBAL(void){
  1320. __asm {
  1321. // syntax:
  1322. // input 16 bit offset is bit15..bit0
  1323. // ppage values: ppage7..ppage0
  1324. // epage values: epage7..epage0
  1325. // dpage values: dpage7..dpage0
  1326. // rpage values: rpage7..rpage0
  1327. // stack must be between $1000 and $3FFF.
  1328. // actually placing the stack at $1000 implies that the RPAGE register is not set (and correctly initialized)
  1329. CPX #0x2000
  1330. BLO PAGED_RAM
  1331. // Map 0x2000 to 0x0FE000 (0x0FA000 for HCS12XE RAM mapping is enabled)
  1332. LDAB #0x0F
  1333. #ifndef __HCS12XE_RAMHM_SET__
  1334. LEAX (0xE000-0x2000),X ;// LEAX is one cycle faster than ADDX #
  1335. #else
  1336. LEAX (0xA000-0x2000),X ;// LEAX is one cycle faster than ADDX #
  1337. #endif
  1338. RTS
  1339. PAGED_RAM:
  1340. PSHX
  1341. LDAB __RPAGE_ADR__
  1342. LDAA #0x20
  1343. MUL
  1344. EORB 0,SP
  1345. EORB #0x10 ;// clear 1 bit
  1346. STAB 0,SP
  1347. TFR A,B
  1348. PULX
  1349. RTS
  1350. }
  1351. }
  1352. /*--------------------------- _CONV_LOGICAL_TO_GLOBAL --------------------------------
  1353. Convert 24 bit global to 24 bit logical pointer
  1354. ("char*__far" to "char*__gpage")
  1355. Arguments :
  1356. - B : page part of logical address
  1357. - X : 16 offset part of logical address
  1358. Postcondition :
  1359. - B == page of returned global address
  1360. - X == offset of returned global address
  1361. - Y remains unchanged
  1362. - A remains unchanged
  1363. */
  1364. /*--------------------------- Convert 24 bit logical to 24 bit global pointer ----------------------------------*/
  1365. /* B:X = Logical(B:X) */
  1366. #ifdef __cplusplus
  1367. extern "C"
  1368. #endif
  1369. #pragma NO_FRAME
  1370. #pragma NO_ENTRY
  1371. #pragma NO_EXIT
  1372. void NEAR _CONV_LOGICAL_TO_GLOBAL(void) {
  1373. __asm {
  1374. // syntax:
  1375. // input 16 bit offset is bit15..bit0
  1376. // ppage values: ppage7..ppage0
  1377. // epage values: epage7..epage0
  1378. // dpage values: dpage7..dpage0
  1379. // rpage values: rpage7..rpage0
  1380. PSHA ;// save A across this routine.
  1381. PSHX ;// D contains bit15..bit0
  1382. PSHB ;// store page
  1383. TFR X,D ;// D is cheaper to shift
  1384. LSLD ;// D contains 0 bit14..bit0, C contains bit15
  1385. BCC Below8000 ;// bit15 == 0?
  1386. // from 0x8000 to 0xFFFF
  1387. LSLD ;// D contains 00 bit13..bit0, C contains bit14
  1388. BCC BelowC000
  1389. PULB ;// cleanup stack
  1390. LDAB #0x7F
  1391. PULX
  1392. PULA
  1393. RTS ;// returns 0b0111 1111 11 bit13...bit0
  1394. BelowC000: ;// from 0x8000 to 0xBFFF
  1395. TFR D,X
  1396. PULB ;// cleanup stack
  1397. SEC
  1398. RORB
  1399. RORX
  1400. LSRB
  1401. RORX
  1402. LEAS 2,SP
  1403. PULA
  1404. RTS ;// returns 0b01 ppage7..ppage0 bit13...bit0
  1405. Below8000:
  1406. LSLD ;// D contains 00 bit13..bit0, C contains bit14
  1407. BCC Below4000
  1408. ;// from 0x4000 to 0x7FFF
  1409. PULB ;// cleanup stack
  1410. PULX
  1411. #ifndef __HCS12XE_RAMHM_SET__
  1412. LDAB #0x7F
  1413. #else
  1414. LEAX (0xC000-0x4000),X
  1415. LDAB #0x0F
  1416. #endif
  1417. PULA
  1418. RTS ;// returns 0b0111 1111 01 bit13...bit0
  1419. Below4000:
  1420. LSLD ;// D contains 000 bit12..bit0, C contains bit13
  1421. BCC Below2000
  1422. // from 0x2000 to 0x3FFF
  1423. PULB ;// cleanup stack
  1424. PULX
  1425. #ifndef __HCS12XE_RAMHM_SET__
  1426. LEAX (0xE000-0x2000),X
  1427. #else
  1428. LEAX (0xA000-0x2000),X
  1429. #endif
  1430. LDAB #0x0F
  1431. PULA
  1432. RTS ;// returns 0b0000 1111 111 bit12...bit0
  1433. Below2000:
  1434. LSLD ;// D contains 0000 bit11..bit0, C contains bit12
  1435. BCC Below1000
  1436. // from 0x1000 to 0x1FFF
  1437. PULB
  1438. LDAA #0x10
  1439. MUL
  1440. EORB 0,SP
  1441. EORB #0x10 ;// clear 1 bit
  1442. STAB 0,SP
  1443. TFR A,B
  1444. PULX
  1445. PULA
  1446. RTS
  1447. Below1000:
  1448. LSLD ;// D contains 0000 0 bit10..bit0, C contains bit11
  1449. BCC Below0800
  1450. // from 0x0800 to 0x0FFF
  1451. LSLD ;// D contains 0000 00 bit9..bit0, C contains bit10
  1452. BCC Below0C00
  1453. // from 0x0C00 to 0x0FFF
  1454. PULB ;// cleanup stack
  1455. LDAB #0x13
  1456. PULX
  1457. LEAX 0xF000,X
  1458. PULA
  1459. RTS ;// returns 0b0001 0011 1111 11 bit9...bit0
  1460. Below0C00:
  1461. // from 0x0800 to 0x0BFF
  1462. PULB
  1463. LDAA #0x04
  1464. MUL
  1465. EORB 0,SP
  1466. EORB #0x08
  1467. STAB 0,SP
  1468. TFR A,B
  1469. ORAB #0b00010000
  1470. PULX
  1471. PULA
  1472. RTS
  1473. Below0800:
  1474. PULB
  1475. PULX
  1476. PULA
  1477. CLRB
  1478. RTS
  1479. }
  1480. }
  1481. /*--------------------------- _FAR_COPY_RC HCS12X Routines --------------------------------
  1482. copy larger far memory blocks
  1483. There are the following memory block copy routines:
  1484. _COPY : 16 bit logical copies.
  1485. Src and dest are both near. Note: implemented in rtshc12.c and not here.
  1486. _FAR_COPY_RC HC12/HCS12 struct copy routine.
  1487. Expects HC12/HCS12 logical 24 bit address.
  1488. Note: Does not exist for the HCS12X.
  1489. The HC12/HCS12 implementation is implemented above.
  1490. _FAR_COPY_GLOBAL_GLOBAL_RC:
  1491. _FAR_COPY_GLOBAL_LOGICAL_RC:
  1492. _FAR_COPY_LOGICAL_GLOBAL_RC:
  1493. _FAR_COPY_LOGICAL_LOGICAL_RC:
  1494. _FAR_COPY_NEAR_GLOBAL_RC:
  1495. _FAR_COPY_NEAR_LOGICAL_RC:
  1496. _FAR_COPY_GLOBAL_NEAR_RC:
  1497. _FAR_COPY_LOGICAL_NEAR_RC: HCS12X specific far copy routine. The name describes what the src/dest address format are.
  1498. All near src arguments are passed in X, all 24 bit src in X/B.
  1499. All near dest arguments are passed in Y, all 24 bit src in Y/A.
  1500. (Note: HC12 _FAR_COPY_RC is using X/A as src and Y/B as dest, so the register usage is not the same!)
  1501. Arguments :
  1502. - B:X : src address (for NEAR/_COPY: only X)
  1503. - A:Y : dest address (for NEAR/_COPY: only Y)
  1504. - number of bytes to be copied behind return address (for _COPY: in D register). The number of bytes is always > 0
  1505. Result :
  1506. - memory area copied
  1507. - no registers are saved, i.e. all registers may be destroyed
  1508. - for _COPY: D contains 0.
  1509. - for HCS12X _FAR_COPY_... routines: GPAGE state is unknown
  1510. */
  1511. #ifdef __cplusplus
  1512. extern "C"
  1513. #endif
  1514. #pragma NO_ENTRY
  1515. #pragma NO_EXIT
  1516. #pragma NO_FRAME
  1517. void NEAR _FAR_COPY_GLOBAL_GLOBAL_RC(void) {
  1518. __asm {
  1519. PSHD
  1520. PSHY
  1521. LDY 4,SP ;// load return address
  1522. LDD 2,Y+ ;// load size
  1523. STY 4,SP ;// store return address
  1524. PULY
  1525. PSHD
  1526. LDAB 3,SP
  1527. Loop:
  1528. STAB __GPAGE_ADR__
  1529. GLDAA 1,X+
  1530. MOVB 2,SP,__GPAGE_ADR__
  1531. GSTAA 1,Y+
  1532. DECW 0,SP
  1533. BNE Loop
  1534. LEAS 4,SP
  1535. _SRET ;// debug info only: This is the last instr of a function with a special return
  1536. RTS
  1537. }
  1538. }
  1539. #ifdef __cplusplus
  1540. extern "C"
  1541. #endif
  1542. #pragma NO_ENTRY
  1543. #pragma NO_EXIT
  1544. #pragma NO_FRAME
  1545. void NEAR _SET_PAGE_REG_HCS12X(void) {
  1546. // Sets the page contained in A to the register controlling the logical addr contained in X.
  1547. // saves the old page before and returns it in A together with the page address just below the return address.
  1548. // X/Y both remain valid.
  1549. __asm {
  1550. PSHX
  1551. // 0000..FFFF
  1552. CPX #0x8000
  1553. BLO _LO8000
  1554. LDX #__PPAGE_ADR__
  1555. BRA Handle
  1556. _LO8000:
  1557. // 0000..7FFF
  1558. CPX #0x1000
  1559. BLO _LO1000
  1560. LDX #__RPAGE_ADR__
  1561. BRA Handle
  1562. _LO1000:
  1563. LDX #__EPAGE_ADR__
  1564. Handle:
  1565. LDAA 0,X ;// load old page register content
  1566. STAB 0,X ;// set new page register
  1567. STX 4,SP
  1568. PULX
  1569. RTS
  1570. }
  1571. }
  1572. #ifdef __cplusplus
  1573. extern "C"
  1574. #endif
  1575. #pragma NO_ENTRY
  1576. #pragma NO_EXIT
  1577. #pragma NO_FRAME
  1578. void NEAR _FAR_COPY_GLOBAL_LOGICAL_RC(void) {
  1579. __asm {
  1580. STAB __GPAGE_ADR__
  1581. EXG X,Y
  1582. TFR A,B
  1583. PSHY ;// space to store size
  1584. PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
  1585. LDY 4,SP ;// load return address
  1586. LDX 2,Y+ ;// load size
  1587. STY 4,SP
  1588. LDY 2,SP ;// restore dest pointer
  1589. STX 2,SP ;// store size
  1590. LDX 0,SP ;// reload src pointer
  1591. __PIC_JSR(_SET_PAGE_REG_HCS12X)
  1592. Loop: GLDAB 1,Y+
  1593. STAB 1,X+
  1594. DECW 2,SP
  1595. BNE Loop
  1596. PULX ;// reload page register address
  1597. STAA 0,X ;// restore old page content (necessary if it was PPAGE)
  1598. PULX ;// clean up stack
  1599. _SRET ;// debug info only: This is the last instr of a function with a special return
  1600. RTS
  1601. }
  1602. }
  1603. #ifdef __cplusplus
  1604. extern "C"
  1605. #endif
  1606. #pragma NO_ENTRY
  1607. #pragma NO_EXIT
  1608. #pragma NO_FRAME
  1609. void NEAR _FAR_COPY_LOGICAL_GLOBAL_RC(void) {
  1610. __asm {
  1611. STAA __GPAGE_ADR__
  1612. PSHY ;// space to store size
  1613. PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
  1614. LDY 4,SP ;// load return address
  1615. LDX 2,Y+ ;// load size
  1616. STY 4,SP
  1617. LDY 2,SP ;// restore dest pointer
  1618. STX 2,SP ;// store size
  1619. LDX 0,SP ;// reload src pointer
  1620. __PIC_JSR(_SET_PAGE_REG_HCS12X)
  1621. Loop: LDAB 1,X+
  1622. GSTAB 1,Y+
  1623. DECW 2,SP
  1624. BNE Loop
  1625. PULX
  1626. STAA 0,X ;// restore old page content (necessary if it was PPAGE)
  1627. PULX ;// clean up stack
  1628. _SRET ;// debug info only: This is the last instr of a function with a special return
  1629. RTS
  1630. }
  1631. }
  1632. #ifdef __cplusplus
  1633. extern "C"
  1634. #endif
  1635. #pragma NO_ENTRY
  1636. #pragma NO_EXIT
  1637. #pragma NO_FRAME
  1638. void NEAR _FAR_COPY_LOGICAL_LOGICAL_RC(void) {
  1639. __asm {
  1640. PSHA
  1641. __PIC_JSR(_CONV_LOGICAL_TO_GLOBAL);
  1642. PULA
  1643. __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
  1644. }
  1645. }
  1646. #ifdef __cplusplus
  1647. extern "C"
  1648. #endif
  1649. #pragma NO_ENTRY
  1650. #pragma NO_EXIT
  1651. #pragma NO_FRAME
  1652. void NEAR _FAR_COPY_NEAR_GLOBAL_RC(void) {
  1653. __asm {
  1654. CLRB
  1655. __PIC_JMP(_FAR_COPY_LOGICAL_GLOBAL_RC);
  1656. }
  1657. }
  1658. #ifdef __cplusplus
  1659. extern "C"
  1660. #endif
  1661. #pragma NO_ENTRY
  1662. #pragma NO_EXIT
  1663. #pragma NO_FRAME
  1664. void NEAR _FAR_COPY_NEAR_LOGICAL_RC(void) {
  1665. __asm {
  1666. PSHA
  1667. __PIC_JSR(_CONV_NEAR_TO_GLOBAL);
  1668. PULA
  1669. __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
  1670. }
  1671. }
  1672. #ifdef __cplusplus
  1673. extern "C"
  1674. #endif
  1675. #pragma NO_ENTRY
  1676. #pragma NO_EXIT
  1677. #pragma NO_FRAME
  1678. void NEAR _FAR_COPY_GLOBAL_NEAR_RC(void) {
  1679. __asm {
  1680. CLRA /* near to logical (we may have to use another runtime if this gets non trivial as well :-( */
  1681. __PIC_JMP(_FAR_COPY_GLOBAL_LOGICAL_RC);
  1682. }
  1683. }
  1684. #ifdef __cplusplus
  1685. extern "C"
  1686. #endif
  1687. #pragma NO_ENTRY
  1688. #pragma NO_EXIT
  1689. #pragma NO_FRAME
  1690. void NEAR _FAR_COPY_LOGICAL_NEAR_RC(void) {
  1691. __asm {
  1692. EXG A,B
  1693. EXG X,Y
  1694. PSHA
  1695. __PIC_JSR(_CONV_NEAR_TO_GLOBAL);
  1696. PULA
  1697. EXG A,B
  1698. EXG X,Y
  1699. __PIC_JMP(_FAR_COPY_LOGICAL_GLOBAL_RC);
  1700. }
  1701. }
  1702. /* _FAR_COPY_LOGICAL_GLOBAL: is used by some old wizard generated projects. Not used by current setup anymore */
  1703. #ifdef __cplusplus
  1704. extern "C"
  1705. #endif
  1706. #pragma NO_ENTRY
  1707. #pragma NO_EXIT
  1708. #pragma NO_FRAME
  1709. void NEAR _FAR_COPY_LOGICAL_GLOBAL(void) {
  1710. __asm {
  1711. STAA __GPAGE_ADR__
  1712. PSHX ;// allocate some space where _SET_PAGE_REG_HCS12X can return the page
  1713. __PIC_JSR(_SET_PAGE_REG_HCS12X)
  1714. Loop: LDAB 1,X+
  1715. GSTAB 1,Y+
  1716. DECW 4,SP
  1717. BNE Loop
  1718. PULX
  1719. STAA 0,X ;// restore old page content (necessary if it was PPAGE)
  1720. LDX 4,SP+ ;// load return address and clean stack
  1721. JMP 0,X
  1722. }
  1723. }
  1724. #endif /* __HCS12X__ */
  1725. /*----------------- end of code ------------------------------------------------*/