CPU emulatie; half-carry

Status
Niet open voor verdere reacties.

That Guy

Meubilair
Lid geworden
28 nov 2006
Berichten
5.010
Hallo allemaal,



[... Dit is mischien niet het meest practische forum om neer te zetten, maargoed]


ik ben druk bezig met het emuleren van een CPU (Z80); nu staat dit in de docs over de INC r-operatie:
INC n
Description:
Increment register n.

Use with:
n = A,B,C,D,E,H,L,(HL)

Flags affected:
Z - Set if result is zero.
N - Reset.
H - Set if carry from bit 3.
C - Not affected.

Code:
Instruction Parameters Opcode Cycles
------------------------------------
INC         B          04     4
Nu heb ik deze code (daadwerkelijke code is anders, maar het idee is uiteraard hetzelfde):
Code:
void inc_b()
{
   register.B++;

   register.B &= 255;

   register.F |= (register.B == 0) ? flags.ZERO : 0x00;   // zet de zero-flag 'aan' als resultaat 0 is
}
nu moet ik dus deze nog doen:
N - Reset.
H - Set if carry from bit 3.

Dus, hier mijn vragen:

  1. Reset; hoe 'reset' ik een flag? Dus, 0101b en een flag van 0100b moet 0001b worden. Is dit hetzelfde als 0101b - 0100b? (dus gewoon aftrekken?)
  2. Half-carry: hoe check ik op een carry van het 3e bit? Kan ik checken of het groter is dan 0x07 (eh, 3e bit en groter 'aan'), maar alleen als het al niet groter was... oid? Shiften? :confused:

Het hele projectje is echt leuk, alleen de bit/byte-magie wil af en toe nog niet helemaal... Wie o wie kan mij de goede richting op wijzen?




Alvast bedank! :thumb:
 
Laatst bewerkt:
Hey cool, Z80 assembly. Ik voel me weer jong ;)

Gedeeltelijke antwoorden (het is al weer even geleden, jaartje of 20)
1) Reset van een flag doe je met een AND operatie. in jouw geval AND 11111110b. Dit reset je laatste bit naar 0.
2) Half-carry moet ik even over nadenken. Eerste ingeving is dat als er een carry plaats vindt de links 4 bits zijn gewijzigd. Een simpele controle of de linkse 4 bits hetzelfde zijn voor en na de bewerking zou voldoende moeten zijn.
 
Hoi RogerS,


Bedankt, het resetten is gelukt!
Nu zit ik alleen nog met die half-carry. Het moet dus 'aan' als er een carry is vanaf het 3e bit. I weet het niet zeker, maar dit is toch alleen als de waarde eerst 7 was, en daarna werd opgehoogd naar 8?

Code:
bit    8  7  6  5  4  3  2  1
-----------------------------
       0  0  0  0  0  1  1  1     = 7d, 0x07
INC B
       0  0  0  0  1  0  0  0     = 8d, 0x08    <-- bit 3 'overflow', dus half-carry?
of zit ik nu fout met mijn carry-bit definitie?



:thumb:
 
Laatst bewerkt:
Nu ik het voorbeeld zie. Volgens mij heb je het juist.
 
Ik heb de volgende C++ code ergens gevonden, en heb wat overbodige dingen weggehaald:[CPP]void Emulator::CPU_8BIT_INC(BYTE& reg)
{
BYTE before = reg ;

reg++ ;

if (reg == 0)
m_RegisterAF.lo = BitSet(m_RegisterAF.lo, FLAG_Z) ; // zero flag
else
m_RegisterAF.lo = BitReset(m_RegisterAF.lo, FLAG_Z) ; // zie vraag 1

m_RegisterAF.lo = BitReset(m_RegisterAF.lo, FLAG_N) ; // reset subtraction flag

if ((before & 0xF) == 0xF)
m_RegisterAF.lo = BitSet(m_RegisterAF.lo, FLAG_H) ; // de half-carry flag; zie vraag 2
else
m_RegisterAF.lo = BitReset(m_RegisterAF.lo, FLAG_H) ; // ook 1
}[/CPP]De .lo wijst dus naar register F (hi & lo = register AF).


  1. Is er een reden om de zero-flag te resetten, als het geen zero is? De spec zegt niet dat het moet, of zie ik dat verkeerd? Is het normaal om een flag, mocht die gezet kunnen worden, zowiezo eerst te 'resetten'? (nu ik het nogmaals lees klinkt het eigenlijk wel logisch... then again, CPU's zijn redelijk apart soms :p)
  2. Wat ze hier dus doen is inderdaad de oude waarde opslaan; dan AND-en met 0xF; en als het 0xF is, de half-carry flag zetten. Deze code schijnt te werken... dus ligt het aan mij, en klopt de spec die ik eerder had gepost dan niet, of zie ik het verkeerd? Het AND-en met 0xF (15) betekent toch dat de normale carry flag gezet moet worden?!

Het gaat hier overgens niet om de originele Zilog Z80, maar de CPU in de Nintendo Gameboy (sterk erop lijkend maar met minder registers/operaties).




Alvast bedankt :thumb:


[edit]Een andere spec zegt dit:
[...] and [flag] H indicates carry for lower 4bits of the result [...]
Because C and H flags must contain carry-outs for each digit, DAA cannot be used for 16bit operations (which have 4 digits), or for INC/DEC operations (which do not affect C-flag).
Ik ga er nu maar even een nachtje over slapen ;)[/edit]


[edit]
also:
Half-Carry: Set if the correction operation caused a binary carry/borrow
from bit 3 to bit 4.
For this purpose, may be calculated as:
Bit 4 of: A(before) XOR A(after).
[/edit]
 
Laatst bewerkt:
*schop*

Ik ben nogsteeds niet verdergekomen met dit probleem. Overgens zegt de spec dit over SUB B:
Half-carry: Set if no borrow from bit 4.
Iemand die me kan helpen met dit te begrijpen? Hoe werkt borrow precies bij aftrekken? Want bij optellen begrijp ik het zo ongeveer wel...



:thumb:
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan