/***********************************************************

  memory_usage.c

  Z-World, 2001

  Useful little program to show memory usage.
     
  For best table format results use "Terminal" for
  the Stdio window font.

  This program only detects the primary flash if the
  board has more than one flash!

************************************************************/

char readStackSeg();

main()
{
	unsigned long mb,mt,ms,sz;
   int i;


	//********** Show Flash Present ***************
	printf(
		"     Dynamic C detects a flash of %08lx bytes.\n",
			(long)(_FLASH_SIZE_)<<12ul);
	if(_FLASH_SIZE_ != FLASH_SIZE)
		printf(
			"       However, the BIOS set FLASH_SIZE to %08lx bytes\n",
				(long)(FLASH_SIZE)<<12ul);
#ifndef _FLASH_
		printf(
			"     Flash is not being used. This program is compiled to RAM \n");
#else
	printf(
		"     Flash starts at physical address 00000\n");
#endif
	printf("\n");


	
	//********** Show RAM Present ***************
	printf(
	   "     Dynamic C detects a RAM of %08lx bytes\n",(long)(_RAM_SIZE_)<<12ul);
	printf("     Ram starts at physical address %08lx\n",(long)(RAM_START)<<12ul);


	//********** Displa MMU/MIU Registers ***************
	printf("\nMMU Registers:\n");
	printf("     SEGSIZE=%02x\n",MEMBREAK);
	printf("     DATASEGVAL=%02x\n",DATASEGVAL);
	printf("     STACKSEGVAL=%02x\n",readStackSeg());
	printf("     XPC=%02x\n",XMEMSEGVAL);
	printf("\nMIU Bank Registers:\n");
	printf("     MB0CR=%02x\n",MB0CRShadow);
	printf("     MB1CR=%02x\n",MB1CRShadow);
	printf("     MB2CR=%02x\n",MB2CRShadow);
	printf("     MB3CR=%02x\n",MB3CRShadow);
	printf("\n");


	//********** Begin Usage Table ***************
	printf(
	 " \xda-----------------------------------------------------------------------------\xbf"
	 ); 
	printf(
	 " \xB3 PHYSADR LOGADR    SIZE  SIZE(Dec)  USAGE                                    \xB3"
	 ); 

	separator();
	printf(
#ifdef _FLASH_
	 " \xB3 FLASH                                                                       \xB3"
#else
	 " \xB3 RAM                                                                         \xB3"
#endif
	 ); 
	separator();
	 
	//********** Root Code  ***************
	table_entry(0,(long)0,(long)DATAORG,"Reserved by Compiler for Root Code");
	table_entry(0,(long)0,(long)StartUserCode-1,"used by BIOS");
	table_entry((unsigned)StartUserCode,
	  (long)StartUserCode,
	  (long)prog_param.RCE.aaa.a.addr-(long)StartUserCode,
	  "used by this program for root code");

	separator();
	 
	//********** XMem Code  ***************
	table_entry(
		0xffffu,
	  (long)DATAORG,
	  (long)XMEMORYSIZE,
	  "Reserved for Xmem Code");

	mb = 0x0ffffful &
		((unsigned long)prog_param.XCB.aaa.a.addr +
		((unsigned long)prog_param.XCB.aaa.a.base<<12));
	mt = 0x0ffffful &
		((unsigned long)prog_param.XCE.aaa.a.addr +
		((unsigned long)prog_param.XCE.aaa.a.base<<12));
	ms = mt-mb;						

	table_entry(
	   0xffffu,
	   mb,
	   ms,
	   "used by this program for xmem code");

#if (XMEM_RESERVE_SIZE>0)	   
	table_entry(
	   0xffffu,
	   FLASH_SIZE*4096L - DATAORG - XMEM_RESERVE_SIZE,
	   (long)XMEM_RESERVE_SIZE,
	   "used for the File System");
#endif
	separator();
	 
	printf(
#ifdef _FLASH_
	 " \xB3 RAM                                                                         \xB3"
#else
	 " \xB3 MORE RAM (Code and BIOS in RAM option set in compiler options)              \xB3"
#endif
	 ); 
	separator();

	//********** Root RAM ***************
	table_entry(
	   DATAORG,
	   (long)(DATASEGVAL<<12L)+(long)(DATAORG),
	   (long)((MEMBREAK>>4)-(MEMBREAK&0x0f))*4096L,
	   "Reserved for Root Data");

	table_entry(
	   prog_param.RDE.aaa.a.addr,
	   paddr((void *)prog_param.RDE.aaa.a.addr),
	   (long)(prog_param.RDB.aaa.a.addr - prog_param.RDE.aaa.a.addr)+1,
	   "used by this program for root data");

	table_entry(
	   INTVEC_BASE,
	   paddr((void*)(INTVEC_BASE)),0x100ul,
	   "used for the internal vector table");

   table_entry(
      XINTVEC_BASE,
      paddr((void*)(XINTVEC_BASE)),0x100ul,
      "used for the external vector table");

	separator();
	 
	//********** Display xalloc used areas ***************
	// includes RAM space reserved for items already listed
	for(i = RSTORE-1; i>=0; i--)
	{
		if(reserve_Store[i].sz)
		{
			table_entry(
		   	0xffffu,
			   reserve_Store[i].top+1-reserve_Store[i].sz,
		   	reserve_Store[i].sz,
			   "Reserved RAM space");
		}
	}	   

	separator();
	
	//********** Stacks ***************
	table_entry(
	   0xffffu,
   	BaseOfStacks1,
	   SizeOfStacks1,
	   "Stack space");

	if(SizeOfStacks2)
	{
		table_entry(
		   0xffffu,
   		BaseOfStacks2,
		   SizeOfStacks2,
		   "Stack space");
	}
	separator();

	//********** Flash Buffer ***************
	table_entry(
	   0xffffu,
	   FLASH_BUF_PHYS,
	   (long)FLASH_BUF_SIZE,
	   "Used for the flash buffer");

#if (ENABLE_ERROR_LOGGING==1)

	//********** Error Log Buffer ***************
	table_entry(
	   0xffffu,
	   ERRLOG_PHYSICAL_ADDR&0xffff000ul,
	   (long)(ERRLOG_NBLOCKS*4096),
	   "Reserved for the Error log buffer");
	table_entry(
	   0xffffu,
	   ERRLOG_PHYSICAL_ADDR,
	   (long)ERRLOG_LOG_SIZE,
	   "Used for the Error log buffer");
#endif

#if (FS2_RAM_RESERVE!=0)
	table_entry(
	   0xffffu,
	   (long)FS2_RAM_PHYS,
	   FS2_RAM_RESERVE*4096L,
	   "Reserved for File System buffer");

#endif
	separator();

	//********** Display xalloc free areas ***************
	for(i = RSTORE-1; i>=0; i--)
	{
	
		if(xalloc_Store[i].sz)
		{
			sz = xalloc_Store[i].sz - (xalloc_Store[i].top - xalloc_Store[i].free);
			table_entry(
		   	0xe000u,
				xalloc_Store[i].free-sz+1,
				sz,
			   "Free XRAM space for xalloc");
		}
	}	   

	// bottom of table	
	printf(
	 " \xC0-----------------------------------------------------------------------------\xd9\n"
	 ); 
	 
}


table_entry( unsigned logaddr,
             long physaddr,
             long Size,
             char * use
           )
{
	unsigned xAddr;
	unsigned long addr32;
   char     xBase;
   
	// *** base seg entry ***
	if(logaddr<DATAORG)
	{
		printf(" \xB3 %05lx   00:%04x   %05lx %06ld     %-40.38s \xB3",physaddr,logaddr,Size,Size,use); 
	}
	// *** data seg entry ***
	else if(logaddr<(STACKORG))
	{
		printf(" \xB3 %05lx   %02x:%04x   %05lx %06ld     %-40.38s \xB3",physaddr,DATASEGVAL,logaddr,Size,Size,use); 
	}
	// *** stack seg entry ***
	else if(logaddr<0xE000u)
	{
		printf(" \xB3 %05lx   %02x:%04x   %05lx %06ld     %-40.38s \xB3",physaddr,readStackSeg(),logaddr,Size,Size,use); 
	}
	// *** xmem seg entry ***
	// if log address is in E000-FFFF range ignore logical entry parameter 
	// and convert physical address to a an E000-FFFF logical address 
	else
	{
		addr32 = physaddr-0xe000ul;
		xBase = (char)((addr32&0x000ff000L)>>12);
		xAddr = (unsigned)((addr32&0x00000fffL)|0xe000L);

		printf(" \xB3 %05lx   %02x:%04x   %05lx %06ld     %-40.38s \xB3",physaddr,xBase,xAddr,Size,Size,use); 
	}
}


char readStackSeg(){
	static char retval;
   // **** read STACKSEG register **** 
#asm
	ioi ld a,(STACKSEG)
	ld (retval),a
#endasm
	return retval;
}

separator()
{
	printf(
	 " \xC3-----------------------------------------------------------------------------\xB4"
	 ); 
}