Page 1 of 1

Assembly CPU: Flags

Posted: Tue May 31, 2011 1:43 am
by 6T4
I am writing the CPU for my NES emulator in assembly, but I am getting confused by the difference between the assembly I am coding in and the 6502 assembly that the NES uses, particularly the flags.

This is my code for setting/clearing flags:

Code: Select all

MODIFYFLAGS MACRO Sign, Overflow, Zero, Carry

	; Clear all the flags if they are passed.
	pushfd
	IFNB <Sign>
		and CPU.F, 01111111b
	ENDIF
	IFNB <Overflow>
		and CPU.F, 10111111b
	ENDIF
	IFNB <Zero>
		and CPU.F, 11111101b
	ENDIF
	IFNB <Carry>
		and CPU.F, 11111110b
	ENDIF
	popfd
	
	; Set the flags that are passed to the macro.
	
	IFNB <Sign>
		pushfd
		sets dl
		shl dl, 7
		or CPU.F, dl
		popfd
	ENDIF
	IFNB <Overflow>
		pushfd
		seto dl
		shl dl, 6
		or CPU.F, dl
		popfd
	ENDIF
	IFNB <Zero>
		pushfd
		setz dl
		shl dl, 1
		or CPU.F, dl
		popfd
	ENDIF
	IFNB <Carry>
		pushfd
		setc dl
		or CPU.F, dl
		popfd
	ENDIF
ENDM
Does this create separate flags or use the existing flags of the assembly language I am coding in? If it's the latter, is there a way to keep certain instructions from setting flags? Any general information on this would be appreciated.

Posted: Sat Jun 04, 2011 3:26 am
by 6T4
If anybody who knows assembly language, particularly anyone who has coded an emulator in assembly, is reading this, please help. I would like to get my CPU working better before I deal with many other aspects of my emulator. If anyone is confused by what I'm asking, I found the following document that discusses this issue (and many other things): http://nesdev.icequake.net/NES%20emulat ... ussion.txt

Posted: Sat Jun 04, 2011 3:36 am
by Nessie
It would be better to put all flags in separate bytes so you can use setCC individually on each flag. Here's how I've been doing it:

Code: Select all

.saveSZCV:
	seto [cpu.flag.v]
.saveSZC:
	setc [cpu.flag.c]
.saveSZ:
	sets [cpu.flag.s]
	setz [cpu.flag.z]
	ret

;
; Read operations
; al = the value read from memory
;
.and:
	and [cpu.a], al
	jmp .saveSZ

.eor:
	xor [cpu.a], al
	jmp .saveSZ

.ora:
	or [cpu.a], al
	jmp .saveSZ

.lda:
	mov [cpu.a], al
	test al, al
	jmp .saveSZ
i.e. cpu.flags is just a struct with one byte for each flag.
Whenever the status register is read (like when it's pushed onto the stack), you will then need to pack those bytes together to an 8-bit value.

Posted: Sat Jun 04, 2011 11:05 am
by Zelex
These days, there really isn't a very good reason that I can think of to code an NES emulator in assembly anymore. With the exception of nemulator, who needs to run 32 emulators at the same time, why would you go through the pain to do that?

Posted: Sat Jun 04, 2011 2:14 pm
by Dwedit
You can always peek at the LoopyNES source code and see how that emulator did it.

Posted: Sat Jun 04, 2011 2:22 pm
by Nessie
Zelex wrote:These days, there really isn't a very good reason that I can think of to code an NES emulator in assembly anymore. [...] why would you go through the pain to do that?
For the same reason people start writing new emulators eventhough there already are plenty of good ones out there - it's just fun to have something to tinker with in your spare time. Working with assembly, you also tend to learn a lot about microprocessors and operating systems in general.
As for optimization, a compiler will almost always do a better job than a human so performance is not a reason to prefer assembly over C++.

But yeah, modern computers are fast enough to emulate the NES perfectly even in a VM. I wrote a "pixel-perfect" emulator in Java a couple of years ago and it ran at full speed. I see you're working on one in JavaScript, should work fine since Google's V8 is incredibly fast.

I wonder if we'll ever see a NES emu written in python or perl? :)

Posted: Sat Jun 04, 2011 2:28 pm
by Zelex
lol :) NES emulator in perl... oh god!

Yeah, learning and experimenting is always a good reason! :)

Posted: Sat Jun 04, 2011 5:33 pm
by koitsu
I might be one of the only people left (?) who has done a 6502 emulator in actual x86 assembly. I wonder how many people here remember the qNES project (no, it was never released).

It'll be a cold day in hell before I re-learn x86 though. Worst processor on the planet. Ugh.

Posted: Sat Jun 04, 2011 7:33 pm
by Dwedit
Hey, x86 has its uses... Disassembling and hacking Japanese Windows programs so you can translate them, checking how good a compiler is at optimizing code, and that's about it.

Re: Assembly CPU: Flags

Posted: Sat Jun 04, 2011 8:09 pm
by thefox
6T4 wrote:This is my code for setting/clearing flags:

Code: Select all

MODIFYFLAGS MACRO Sign, Overflow, Zero, Carry
Does this create separate flags or use the existing flags of the assembly language I am coding in?
If it's your code, surely you should know what it does? [But it's not "your code", it's a direct copy from cpu.asm of NEStreme. Might be a good idea to mention that...] I'm sorry but you can't expect somebody to walk you through all of this.

Posted: Sat Jun 04, 2011 9:51 pm
by 6T4
Thank you for the replies so far, especially the example from Nessie. I will continue to work on this and let everyone know my progress.
Dwedit wrote:You can always peek at the LoopyNES source code and see how that emulator did it.
I wasn't aware that LoopyNES was open source. Do you have a link to its source code?
koitsu wrote:I wonder how many people here remember the qNES project (no, it was never released).
You mean QuantumNES? I removed the buggy CPU from it and corrected the iNES header viewer and released that as NESFaCE Version 0.01 Alpha.
thefox wrote:But it's not "your code", it's a direct copy from cpu.asm of NEStreme. Might be a good idea to mention that...
By "my code", I meant the code I was currently using. I did not intend to imply that it was my original work. I have stated on this forum before that I was basing my emulator on NEStreme (and will be basing it on many other emulators in the future). Right now, I am studying the errors in NEStreme to correct them and/or program some areas in a more optimal way to eventually become NESFaCE. However, I agree that maybe I should have been clearer about this. I will try to be more careful in the future.

Posted: Sat Jun 04, 2011 10:03 pm
by koitsu
6T4 wrote:
koitsu wrote:I wonder how many people here remember the qNES project (no, it was never released).
You mean QuantumNES? I removed the buggy CPU from it and corrected the iNES header viewer and released that as NESFaCE Version 0.01 Alpha.
Nope, this qNES. Probably before your time (note article date). God damn I'm old. Anyway the article should amuse folks present-day, since it was before we knew what we do now (no decimal mode, different PPU behaviour, etc.). Here's a brief mention of the discontinuation of qNES. Ahh, memories of my old projects...

Posted: Sat Jun 04, 2011 10:21 pm
by Dwedit
6T4 wrote:
Dwedit wrote:You can always peek at the LoopyNES source code and see how that emulator did it.
I wasn't aware that LoopyNES was open source. Do you have a link to its source code?
Look on his page, http://home.comcast.net/~olimar/NES/

Posted: Sun Jun 05, 2011 5:18 am
by mic_
I wonder if we'll ever see a NES emu written in python or perl?
I began writing an NES emulator in Perl back in 2004 or something like that, but I ditched it after a while to work on other projects. I think I had finished most of the CPU, plus some other stuff, but I don't know if I still have the code.