//------------------------------------------------------------------------------
//  TOPPERS/ASP Windows Debug Environment
//  Copyright (C) 2010-2011 Cores Co., Ltd. Japan
//------------------------------------------------------------------------------
// $Id: core_support.cpp 92 2011-08-07 05:57:30Z nagasima $
#include "StdAfx.h"
#include "WinKernel.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// 贋ＩＴＲＯＮカーネル
CKernel *g_Kernel;

volatile bool faultmask;
volatile bool primask;
volatile uint32_t basepri;
volatile uint32_t control;
volatile uint32_t ipsr;

/*
 *  スタートアップルーチン（リセット用）
 */
void _start(void)
{
}

/*
 *  タスクディスパッチャ
 */
void dispatch(void)
{
	g_Kernel->Dispatch();
}

/*
 *  CPU例外エントリ
 *
 *  割込みエントリと処理の内容は同等だが，ログの種類が異なるため，
 *  分けている．
 */
void core_exc_entry(void)
{
}

/*
 *  割込みエントリ
 */
void core_int_entry(void)
{
}

/*
 *  SVCハンドラ
 */
void svc_handler(void)
{
}

/*
 *  現在のコンテキストを捨ててディスパッチ
 */
void exit_and_dispatch(void)
{
	TCB *Task = get_tcb_self(TSK_SELF);
	t_unlock_cpu();
	g_Kernel->ReleaseCPUContext((CCPUContext *)Task->tskctxb.cpu_context);
}

/*
 *  カーネルの終了処理の呼出し
 *
 *  スタックを非タスクコンテキスト用に切り替え．
 *  
 */
void call_exit_kernel(void)
{
	g_Kernel->Terminate();
}

/*
 *  タスク起動処理
 *
 */ 
void start_r(void)
{
	lock_flag = false;
	basepri = 0;
}

/*
 *  FAULTMASKのセット
 */
void set_faultmask(void)
{
	faultmask = true;
}

/*
 *  FAULTMASKのクリア
 */
void clear_faultmask(void)
{
	faultmask = false;
}

/*
 *  PRIMASKのセット
 */
void set_primask(void)
{
	primask = true;
}

/*
 *  PRIMASKのクリア
 */
void clear_primask(void)
{
	primask = false;
}

/*
 *  BASEPRIのセット
 */
void set_basepri(uint32_t val)
{
	if(val == IIPM_LOCK){
		if(!g_Kernel->InKernelMode()){
			g_Kernel->LockCPU();
			basepri = val;
		}
	}
	else{
		if(!g_Kernel->InKernelMode()){
			basepri = val;
			g_Kernel->UnlockCPU();
		}
	}
}

/*
 *  BASEPRIの取得
 */
uint32_t get_basepri(void)
{
	return(basepri);
}

/*
 *  CONTROLのセット
 */
void set_control(uint32_t val)
{
	control = val;
}

/*
 *  CONTROLの取得
 */
uint32_t get_control(void)
{
	if(g_Kernel->InKernelMode())
		control &= ~CONTROL_PSP;
	else
		control |= CONTROL_PSP;
	return(control);
}

/*
 *  ステータスレジスタ（CPSR）の現在値の読出し
 */
uint32_t get_ipsr(void)
{
	return(ipsr);
}

/*
 *  NMIを除くすべての割込みの禁止
 */
bool_t TOPPERS_disint(void)
{
	bool val = faultmask;

	if (!val) {
		g_Kernel->LockCPU();
		faultmask = true;
	}

	return val;
}

void TOPPERS_enaint(bool_t locked)
{
	if (!locked) {
		faultmask = false;
		g_Kernel->UnlockCPU();
	}
}

void x_define_inh(uint_t inhno, FP int_entry)
{
	g_Kernel->DefineInterruptHandler(inhno, int_entry);
}

//---------------------------------------------------------------------------
//  エンディアンの反転
//---------------------------------------------------------------------------
#ifndef SIL_REV_ENDIAN_H
#define	SIL_REV_ENDIAN_H(data) \
	((uint16_t)((((uint16_t)(data) & 0xff) << 8) | (((uint16_t)(data) >> 8) & 0xff)))
#endif /* SIL_REV_ENDIAN_H */

#ifndef SIL_REV_ENDIAN_W
#define	SIL_REV_ENDIAN_W(data) \
	((uint32_t)((((uint32_t)(data) & 0xff) << 24) | (((uint32_t)(data) & 0xff00) << 8) \
		| (((uint32_t)(data)>> 8) & 0xff00) | (((uint32_t)(data) >> 24) & 0xff)))
#endif /* SIL_REV_ENDIAN_H */

//---------------------------------------------------------------------------
//  8ビット単位の読出し／書込み
//---------------------------------------------------------------------------
uint8_t sil_reb_mem(void * mem)
{
	return g_Kernel->GetByte((unsigned int)mem);
}

void sil_wrb_mem(void * mem, uint8_t data)
{
	g_Kernel->SetByte((unsigned int)mem, data);
}

//---------------------------------------------------------------------------
//  16ビット単位の読出し／書込み
//---------------------------------------------------------------------------
uint16_t sil_reh_mem(void * mem)
{
	return g_Kernel->GetUInt16((unsigned int)mem);
}

void sil_wrh_mem(void * mem, uint16_t data)
{
	g_Kernel->SetUInt16((unsigned int)mem, data);
}

uint16_t sil_reh_bem(void * mem)
{
	uint16_t	data;

	data = g_Kernel->GetUInt16((unsigned int)mem);

	return(SIL_REV_ENDIAN_H(data));
}

void sil_wrh_bem(void * mem, uint16_t data)
{
	sil_wrh_mem(mem, SIL_REV_ENDIAN_H(data));
}

//---------------------------------------------------------------------------
//  32ビット単位の読出し／書込み
//---------------------------------------------------------------------------
uint32_t sil_rew_mem(void * mem)
{
	return g_Kernel->GetUInt32((unsigned int)mem);
}

void sil_wrw_mem(void * mem, uint32_t data)
{
	g_Kernel->SetUInt32((unsigned int)mem, data);
}

uint32_t sil_rew_bem(void * mem)
{
	uint32_t	data;

	data = g_Kernel->GetUInt32((unsigned int)mem);

	return(SIL_REV_ENDIAN_W(data));
}

void sil_wrw_bem(void * mem, uint32_t data)
{
	g_Kernel->SetUInt32((unsigned int)mem, SIL_REV_ENDIAN_W(data));
}

extern "C" void Throw()
{
	throw 1;
}

extern "C" SYSUTM trace_get_tim_utime_arch(void)
{
	__int64 now, frequency, quotient, modulus;
	g_Kernel->GetSystemTime(&now, &frequency);
	// 数値を小さくしておく
	quotient = now / frequency;
	modulus = now % frequency;
	// (1000000 * now) / frequency を計算
	return 1000000 * quotient + (1000000 * modulus) / frequency;
}

