Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add flag operating utility functions #19

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package z80

// Flag is the flag value used for GetFlag etc.
// Each value can be combined with the OR (|) operator.
type Flag uint8

const (
FlagC Flag = 0x01 // FlagC is carry flag.
FlagN Flag = 0x02 // FlagN is subtract flag.
FlagPV Flag = 0x04 // FlagPV is parity/overflow flag.
FlagH Flag = 0x10 // FlagH is half carry flag.
FlagZ Flag = 0x40 // FlagZ is zero flag.
FlagS Flag = 0x80 // FlagS is sign flag.

Flag3 Flag = 0x08 // Flag3 is undefined flag, at 3rd from LSB.
Flag5 Flag = 0x20 // Flag5 is undefined flag, at 5th from LSB.
)

// GetFlag gets a flag status. For available flags, see Flag type. When
// multiple flags are combined, if any one of them is true, this returns true.
func (gpr GPR) GetFlag(f Flag) bool {
return gpr.AF.Lo&uint8(f) != 0
}

// SetFlag sets the specified flag to true. For available flags, see Flag
// type. When multiple flags are combined, all flags are set to true.
func (gpr *GPR) SetFlag(f Flag) {
gpr.AF.Lo |= uint8(f)
}

// ResetFlag resets the specified flag to false. Fo available flags, see Flag
// type. When multiple flags are combined, all flags are set to false.
func (gpr *GPR) ResetFlag(f Flag) {
gpr.AF.Lo &= ^uint8(f)
}
126 changes: 126 additions & 0 deletions flag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package z80_test

import (
"testing"

"github.com/koron-go/z80"
)

func TestGetFlag(t *testing.T) {
for i, c := range []struct {
lo uint8
flag z80.Flag
want bool
}{
{0b00000001, z80.FlagC, true},
{0b00000000, z80.FlagC, false},
{0b11111110, z80.FlagC, false},

{0b00000010, z80.FlagN, true},
{0b00000000, z80.FlagN, false},
{0b11111101, z80.FlagN, false},

{0b00000100, z80.FlagPV, true},
{0b00000000, z80.FlagPV, false},
{0b11111011, z80.FlagPV, false},

{0b00010000, z80.FlagH, true},
{0b00000000, z80.FlagH, false},
{0b11100111, z80.FlagH, false},

{0b01000000, z80.FlagZ, true},
{0b00000000, z80.FlagZ, false},
{0b10111111, z80.FlagZ, false},

{0b10000000, z80.FlagS, true},
{0b00000000, z80.FlagS, false},
{0b01111111, z80.FlagS, false},
} {
var cpu z80.CPU
cpu.AF.Lo = c.lo
got := cpu.GetFlag(c.flag)
if got != c.want {
t.Errorf("unexpected value: %d %+v: got=%t", i, c, got)
}
}
}

func TestSetFlag(t *testing.T) {
for i, c := range []struct {
prev uint8
flag z80.Flag
want uint8
}{
{0b00000000, z80.FlagC, 0b00000001},
{0b00000001, z80.FlagC, 0b00000001},
{0b11111110, z80.FlagC, 0b11111111},

{0b00000000, z80.FlagN, 0b00000010},
{0b00000010, z80.FlagN, 0b00000010},
{0b11111101, z80.FlagN, 0b11111111},

{0b00000000, z80.FlagPV, 0b00000100},
{0b00000100, z80.FlagPV, 0b00000100},
{0b11111011, z80.FlagPV, 0b11111111},

{0b00000000, z80.FlagH, 0b00010000},
{0b00010000, z80.FlagH, 0b00010000},
{0b11101111, z80.FlagH, 0b11111111},

{0b00000000, z80.FlagZ, 0b01000000},
{0b01000000, z80.FlagZ, 0b01000000},
{0b10111111, z80.FlagZ, 0b11111111},

{0b00000000, z80.FlagS, 0b10000000},
{0b10000000, z80.FlagS, 0b10000000},
{0b01111111, z80.FlagS, 0b11111111},
} {
var cpu z80.CPU
cpu.AF.Lo = c.prev
cpu.SetFlag(c.flag)
got := cpu.AF.Lo
if got != c.want {
t.Errorf("unexpected value: %d {prev:%08b flag:0x%02x want:%08b}: got=%08b", i, c.prev, c.flag, c.want, got)
}
}
}

func TestResetFlag(t *testing.T) {
for i, c := range []struct {
prev uint8
flag z80.Flag
want uint8
}{
{0b00000001, z80.FlagC, 0b00000000},
{0b00000000, z80.FlagC, 0b00000000},
{0b11111111, z80.FlagC, 0b11111110},

{0b00000010, z80.FlagN, 0b00000000},
{0b00000000, z80.FlagN, 0b00000000},
{0b11111111, z80.FlagN, 0b11111101},

{0b00000100, z80.FlagPV, 0b00000000},
{0b00000000, z80.FlagPV, 0b00000000},
{0b11111111, z80.FlagPV, 0b11111011},

{0b00010000, z80.FlagH, 0b00000000},
{0b00000000, z80.FlagH, 0b00000000},
{0b11111111, z80.FlagH, 0b11101111},

{0b01000000, z80.FlagZ, 0b00000000},
{0b00000000, z80.FlagZ, 0b00000000},
{0b10111111, z80.FlagZ, 0b10111111},

{0b10000000, z80.FlagS, 0b00000000},
{0b00000000, z80.FlagS, 0b00000000},
{0b11111111, z80.FlagS, 0b01111111},
} {
var cpu z80.CPU
cpu.AF.Lo = c.prev
cpu.ResetFlag(c.flag)
got := cpu.AF.Lo
if got != c.want {
t.Errorf("unexpected value: %d {prev:%08b flag:0x%02x want:%08b}: got=%08b", i, c.prev, c.flag, c.want, got)
}
}
}