/*
 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
 *
 * (c) Copyright 1996, 1997, 1998 Gary Henderson (gary@daniver.demon.co.uk) and
 *                                Jerremy Koot (jkoot@snes9x.com)
 *
 * Super FX C emulator code 
 * (c) Copyright 1997, 1998 Ivar (Ivar@snes9x.com) and
 *                          Gary Henderson.
 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
 *
 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
 * DOS port code contains the works of other authors. See headers in
 * individual files.
 *
 * Snes9x homepage: www.snes9x.com
 *
 * Permission to use, copy, modify and distribute Snes9x in both binary and
 * source form, for non-commercial purposes, is hereby granted without fee,
 * providing that this license information and copyright notice appear with
 * all copies and any derived work.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event shall the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Snes9x is freeware for PERSONAL USE only. Commercial users should
 * seek permission of the copyright holders first. Commercial use includes
 * charging money for Snes9x or software derived from Snes9x.
 *
 * The copyright holders request that bug fixes and improvements to the code
 * should be forwarded to them so everyone can benefit from the modifications
 * in future versions.
 *
 * Super NES and Super Nintendo Entertainment System are trademarks of
 * Nintendo Co., Limited and its subsidiary companies.
 */

.macro GetCarry
	movb _Carry, %dl
	shrb %dl
//	cmpb _Carry, $0
.endm

.macro GetNotCarry
	cmpb $1, _Carry
.endm

.macro SetZN
	movb %al, _Zero
	movb %al, _Negative
.endm

.macro Set16ZN
	movb %ah, _Negative
	setnz _Zero
.endm

.macro SetZNC
	setc _Carry
	movb %al, _Negative
	movb %al, _Zero
.endm

.macro Set16ZNC
	setc _Carry
	setnz _Zero
	movb %ah, _Negative
.endm

.macro SetZNCV
	setc _Carry
	seto _Overflow
	movb %al, _Negative
	movb %al, _Zero
.endm

.macro Set16ZNCV
	setc _Carry
	seto _Overflow
	setnz _Zero
	movb %ah, _Negative
.endm

.macro SetZNV
	seto _Overflow
	movb %al, _Negative
	movb %al, _Zero
.endm

.macro Set16ZNV
	seto _Overflow
	setnz _Zero
	movb %ah, _Negative
.endm


/************* IMMEDIATE8 ****************/
.Macro Immediate8 K
	movb (PC), %al
	incl PC
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
.endm

/************* IMMEDIATE16 ****************/
.macro Immediate16 K
	movw (PC), %ax
	addl $2, PC
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
.endm

/************* Relative ****************/
.macro Relative K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
	movl PC, %edx
	movsbl (%edx), %eax
	incl %edx
	movl %edx, PC
	subl PCBase, %edx
	addl %eax, %edx
	andl $0xffff, %edx
.endm

/************* RelativeLong ****************/
.macro RelativeLong K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
	addl $6, CYCLES
#endif
	xorl %eax, %eax
	movl PC, %edx
	movw (%edx), %ax
	addl $2, %edx
	movl %edx, PC
	subl PCBase, %edx
	addl %eax, %edx
	andl $0xffff, %edx
.endm

/************* AbsoluteIndexedIndirect8 ****************/
.macro AbsoluteIndexedIndirect8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	xorl %edx, %edx
	movw XX, %dx
	addw (PC), %dx
	addl $2, PC
	orl  ShiftedPB, %edx
	call S9xGetWord
	movl %eax, %edx
	andl $0xffff, %edx
.endm

/************* AbsoluteIndirectLong8 ****************/
.macro AbsoluteIndirectLong8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	movw (PC), %dx
	addl $2, PC
	andl $0xffff, %edx
	pushl %edx
	call S9xGetWord
	popl %edx
	pushl %eax
	addl $2, %edx
	call S9xGetByte
	popl %edx
	andl $0xff, %eax
	andl $0xffff, %edx
	sall $16, %eax
	orl  %eax, %edx
.endm

.macro AbsoluteIndirect8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	movw (PC), %dx
	addl $2, PC
	andl $0xffff, %edx
	call S9xGetWord
	movl %eax, %edx
	andl $0xffff, %edx
.endm

.macro Absolute8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	movw (PC), %dx
	addl $2, PC
	andl $0xffff, %edx
	orl  ShiftedDB, %edx
.endm

.macro AbsoluteLong8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
	addl MemSpeed, CYCLES
#endif
	movl (PC), %edx
	add $3, PC
	andl $0xffffff, %edx
.endm

.macro Direct8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
#if 0
	cmpb $0, DL
	je .Direct8\K
	addl $6, CYCLES
.Direct8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
.endm

.macro DirectIndirectIndexed8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
#if 0
	cmpb $0, DD
	je .DirectIndirectIndexed8\K
	addl $6, CYCLES
.DirectIndirectIndexed8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	incl PC
	addw DD, %dx
	call S9xGetWord
	movl ShiftedDB, %edx
	movw %ax, %dx
	xorl %eax, %eax
	movw YY, %ax
	addl %eax, %edx
.endm

.macro DirectIndirectIndexedLong8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
#if 0
	cmpb $0, DD
	je .DirectIndirectIndexedLong8\K
	addl $6, CYCLES
.DirectIndirectIndexedLong8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	pushl %edx
	call S9xGetWord
	popl %edx
	pushw %ax
	addw $2, %dx
	call S9xGetByte
	andl $0xff, %eax
	sall $16, %eax
	xorl %edx, %edx
	popw %ax
	movw YY, %dx
	addl %eax, %edx
	andl $0xffffff, %edx
.endm

.macro DirectIndexedIndirect8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
	addl $6, CYCLES
#endif
#if 0
	cmpb $0, DD
	je .DirectIndexedIndirect8\K
	addl $6, CYCLES
.DirectIndexedIndirect8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	addw XX, %dx
	call S9xGetWord
	movl ShiftedDB, %edx
	movw %ax, %dx
.endm

.macro DirectIndexedX8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
	addl $6, CYCLES
#endif
#if 0
	cmpb $0, DD
	je .DirectIndexedX8\K
	addl $6, CYCLES
.DirectIndexedX8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	addw XX, %dx
.endm

.macro DirectIndexedY8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
	addl $6, CYCLES
#endif
#if 0
	cmpb $0, DD
	je .DirectIndexedY8\K
	addl $6, CYCLES
.DirectIndexedY8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	addw YY, %dx
.endm

.macro AbsoluteIndexedX8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	movl ShiftedDB, %edx
	movw (PC), %dx
	xorl %eax, %eax
	addl $2, PC
	movw XX, %ax
	addl %eax, %edx
	andl $0xffffff, %edx
.endm

.macro AbsoluteIndexedY8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
#endif
	movl ShiftedDB, %edx
	movw (PC), %dx
	xorl %eax, %eax
	addl $2, PC
	movw YY, %ax
	addl %eax, %edx
	andl $0xffffff, %edx
.endm

.macro AbsoluteLongIndexedX8 K
#ifdef VAR_CYCLES
	addl MemSpeedx2, CYCLES
	addl MemSpeed, CYCLES
#endif
	movl (PC), %edx
	xorl %eax, %eax
	addl $3, PC
	movw XX, %ax
	addl %eax, %edx
	andl $0xffffff, %edx
.endm

.macro DirectIndirect8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
#if 0
	cmpb $0, DL
	je .DirectIndirect8\K
	addl $6, CYCLES
.DirectIndirect8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	call S9xGetWord
	movl ShiftedDB, %edx
	movw %ax, %dx
.endm

.macro DirectIndirectLong8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
#endif
#if 0
	cmpb $0, DL
	je .DirectIndirectLong8\K
	addl $6, CYCLES
.DirectIndirectLong8\K:
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw DD, %dx
	incl PC
	pushl %edx
	call S9xGetWord
	popl %edx
	pushw %ax
	addw $2, %dx
	call S9xGetByte
	andl $0xff, %eax
	sall $16, %eax
	popw %ax
	movl %eax, %edx
.endm

.macro StackRelative8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
	addl $6, CYCLES
#endif
	xorl %edx, %edx
	movb (PC), %dl
	addw SS, %dx
	incl PC
.endm

.macro StackRelativeIndirectIndexed8 K
#ifdef VAR_CYCLES
	addl MemSpeed, CYCLES
	addl $12, CYCLES
#endif	
	xorl %edx, %edx
	movb (PC), %dl
	addw SS, %dx
	incl PC
	call S9xGetWord
	movl ShiftedDB, %edx
	movw %ax, %dx
	xorl %eax, %eax
	movw YY, %ax
	addl %eax, %edx
	andl $0xffffff, %edx
.endm

.macro BranchCheck0 K
	cmpb $0, BranchSkip
	jz .BranchCheck0S9xExit\K
	movb $0, BranchSkip
	cmpb $0, SoundSkipMethod
	jne .BranchCheck0S9xExit\K
	movl PC, %eax
	subl PCBase, %eax
	cmpw %dx, %ax
	jbe .BranchCheck0S9xExit\K
	jmp MainAsmLoop
.BranchCheck0S9xExit\K:
.endm

.macro BranchCheck1 K
	cmpb $0, BranchSkip
	jz .BranchCheck1S9xExit\K
	movb $0, BranchSkip
	movb SoundSkipMethod, %al
	cmpb $0, %al
	jne .BranchCheck1Not0\K
	movl PC, %eax
	subl PCBase, %eax
	cmpw %dx, %ax
	jbe .BranchCheck1S9xExit\K
	jmp MainAsmLoop
.BranchCheck1Not0\K:
	cmpb $1, %al
	jne .BranchCheck1Not1\K
	jmp MainAsmLoop
.BranchCheck1Not1\K:
	cmpb $3, %al
	jne .BranchCheck1S9xExit\K
	movl PC, %eax
	subl PCBase, %eax
	cmpw %dx, %ax
	jbe .BranchCheck13a\K
	jmp MainAsmLoop
.BranchCheck13a\K:
	movl PCBase, %eax
	andl $0xffff, %edx
	addl %edx, %eax
	movl %eax, PC
.BranchCheck1S9xExit\K:
.endm

.macro BranchCheck2 K
	cmpb $0, BranchSkip
	jz .BranchCheck2S9xExit\K
	movb $0, BranchSkip
	movb SoundSkipMethod, %al
	cmpb $0, %al
	jne .BranchCheck2Not0\K
	movl PC, %eax
	subl PCBase, %eax
	cmpw %dx, %ax
	jbe .BranchCheck2S9xExit\K
	jmp MainAsmLoop
.BranchCheck2Not0\K:
	cmpb $1, %al
	jne .BranchCheck2Not1\K
	movl PCBase, %eax
	andl $0xffff, %edx
	addl %edx, %eax
	movl %eax, PC
	jmp MainAsmLoop
.BranchCheck2Not1\K:
	cmpb $3, %al
	jne .BranchCheck2S9xExit\K
	movl PC, %eax
	subl PCBase, %eax
	cmpw %dx, %ax
	jbe .BranchCheck23a\K
	jmp MainAsmLoop
.BranchCheck23a\K:
	movl PCBase, %eax
	andl $0xffff, %edx
	addl %edx, %eax
	movl %eax, PC
.BranchCheck2S9xExit\K:
.endm

#if 0
.macro PushByte K
#ifdef VAR_CYCLES
	addl $8, CYCLES
#endif	
	xorl %edx, %edx
	movl RAM, %ecx
	movw SS, %dx
	movb %al, (%ecx, %edx)
	decw SS
.endm

.macro PushWord K
#ifdef VAR_CYCLES
	addl $16, CYCLES
#endif	
	xorl %edx, %edx
	movl RAM, %ecx
	movw SS, %dx
	decl %ecx
	movw %ax, (%ecx, %edx)
	subw $2, %dx
	movw %dx, SS
.endm

.macro PullByte K
#ifdef VAR_CYCLES
	addl $8, CYCLES
#endif	
	xorl %edx, %edx
	movl RAM, %eax
	movw SS, %dx
	incl %edx
	movw %dx, SS
	movb (%eax, %edx), %al
.endm

.macro PullWord K
#ifdef VAR_CYCLES
	addl $16, CYCLES
#endif	
	xorl %edx, %edx
	movl RAM, %eax
	movw SS, %edx
	addw $2, %dx
	movw %dx, SS
	movw -1(%eax, %edx), %ax
.endm
#else
.macro PushByte K
	movl SS, %edx
	andl $0xffff, %edx
	call S9xSetByte
	decw SS
.endm

.macro PushWord K
	movl SS, %edx
	decl %dx
	andl $0xffff, %edx
	call S9xSetWord
	movl SS, %edx
	subl $2, %edx
	movw %dx, SS
.endm

.macro PullByte K
	movl SS, %edx
	incl %edx
	movw %dx, SS
	andl $0xffff, %edx
	call S9xGetByte
.endm

.macro PullWord K
	movl SS, %edx
	addw $2, %dx
	movw %dx, SS
	decl %edx
	andl $0xffff, %edx
	call S9xGetWord
.endm
#endif
