;
;	clip65ca.s
;
;	P/ECE MOS6502 Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Fri Jan 28 03:55:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;
#include "clip65ca.h"

	.code
	.align 1

;****************************************************************************
;	
;****************************************************************************

; 割り込みを実行します。
;
; [in]
;		%data	%addr
;		------	------
;	IRQ	0	0xfffe
;	NMI	0	0xfffa
;	BRK	1	0xfffe
;
; [note]
;	* 実行コンテキスト内から利用します。
;	  実行コンテキスト外から直接呼び出すことはできません。
;
	.global	m6502cpu_interrupt
m6502cpu_interrupt:
	add	%PC, %data			; if BRK then PC++
	;
	xcall.d	m6502cpu_pack			; %t0 = PSR
	ld.w	%t0, %data			; *delay*
	xand	%data, %data, ~(1<<4)		; if BRK then B=1 else B=0
	xsll	%t0, 4
	or	%t0, %data
	;
	ext	m6502mem@ah			; %data = PC
	ext	m6502mem@al
	sub	%data, %PC
	xcall.d	m6502cpu_push			; Push HI(PC)
	rr	%data, 8			; *delay*
	xcall.d	m6502cpu_push			; Push Lo(PC)
	rl	%data, 8			; *delay*
	xcall.d	m6502cpu_push			; Push PSR
	ld.w	%data, %t0			; *delay*
	;
	ext	m6502mem@ah			; %PC = &mem[mem[addr]]
	ext	m6502mem@al
	ld.uh	%PC, [%addr]
	ext	m6502mem@ah
	ext	m6502mem@al
	add	%PC, %PC
	;
	xbset	[%CPU+BDI], 2			; IRQをマスクします。
	xbclr	[%CPU+FLAGS], 0			; 割り込み発生により、WAIを解除します。
	ret

; 保留されているIRQ要求を調べ、実行可能ならば実行します。
;
; [note]
;	* 実行コンテキスト内から利用します。
;	  実行コンテキスト外から直接呼び出すことはできません。
;
	.global	m6502cpu_check_pending
m6502cpu_check_pending:
	xbtst	[%CPU+BDI], 2			; IRQがマスクされていないか?
	xjrne	m6502cpu_check_pending_EXIT
	xbtst	[%CPU+FLAGS], 1			; IRQ要求が保留されているか?
	xjreq	m6502cpu_check_pending_EXIT
	xbclr	[%CPU+FLAGS], 1			; IRQ要求フラグをクリアします。
	xld.w	%addr, 0xfffe			; IRQを実行します。
	xcall.d	m6502cpu_interrupt
	ld.w	%data, 0			; *delay*
m6502cpu_check_pending_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

; IRQを要求します。
;
; [note]
;	* 実行コンテキスト外から呼ばれます。
;	  実行コンテキスト内から呼び出してはいけません。
;
	.global	m6502cpu_irq
m6502cpu_irq:
	pushn	%r3
	xcall	m6502cpu_enter			; 実行コンテキストを取り出します。
	xbset	[%CPU+FLAGS], 1			; IRQ要求フラグをセットします。
	xcall	m6502cpu_check_pending		; 直ちにIRQ実行可能か調べます。
	xcall	m6502cpu_leave			; 実行コンテキストを書き戻します。
	popn	%r3
	ret

; NMIを実行します。
;
; [note]
;	* 実行コンテキスト外から呼ばれます。
;	  実行コンテキスト内から呼び出してはいけません。
;
	.global	m6502cpu_nmi
m6502cpu_nmi:
	pushn	%r3
	xcall	m6502cpu_enter			; 実行コンテキストを取り出します。
	xld.w	%addr, 0xfffa			; NMIを実行します。
	xcall.d	m6502cpu_interrupt
	ld.w	%data, 0			; *delay*
	xcall	m6502cpu_leave			; 実行コンテキストを書き戻します。
	popn	%r3
	ret

;****************************************************************************
;	
;****************************************************************************

	.global	m6502cpu_ERR
m6502cpu_ERR:
	xcall	m6502cpu_leave		; 実行コンテキストを抜けます。
	xjp	m6502cpu_err		; C言語版のエラールーチンへ。

;****************************************************************************
;	
;****************************************************************************
