//------------------------------------------------------------------------------
//  TOPPERS/ASP Windows Debug Environment
//  Copyright (C) 2010-2011 Cores Co., Ltd. Japan
//------------------------------------------------------------------------------
// $Id: core_support.cpp 118 2013-02-12 13:05:51Z nagasima $
#include "StdAfx.h"
#include "WinKernel.h"

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

// 贋ＩＴＲＯＮカーネル
extern 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);
}

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;
}

