mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package z80em
|
|
|
|
func (z *Z80Type) opcodeCB() {
|
|
z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f)
|
|
z.PC++
|
|
opcode := z.core.M1MemRead(z.PC)
|
|
bitNumber := (opcode & 0x38) >> 3
|
|
regCode := opcode & 0x07
|
|
if opcode < 0x40 {
|
|
// Shift/rotate instructions
|
|
opArray := []OpShift{z.doRlc, z.doRrc, z.doRl, z.doRr, z.doSla, z.doSra, z.doSll, z.doSrl}
|
|
switch regCode {
|
|
case 0:
|
|
z.B = opArray[bitNumber](z.B)
|
|
case 1:
|
|
z.C = opArray[bitNumber](z.C)
|
|
case 2:
|
|
z.D = opArray[bitNumber](z.D)
|
|
case 3:
|
|
z.E = opArray[bitNumber](z.E)
|
|
case 4:
|
|
z.H = opArray[bitNumber](z.H)
|
|
case 5:
|
|
z.L = opArray[bitNumber](z.L)
|
|
case 6:
|
|
z.core.MemWrite(z.hl(), opArray[bitNumber](z.core.MemRead(z.hl())))
|
|
default:
|
|
z.A = opArray[bitNumber](z.A)
|
|
}
|
|
} else if opcode < 0x80 {
|
|
// BIT instructions
|
|
switch regCode {
|
|
case 0:
|
|
z.Flags.Z = z.B&(1<<bitNumber) == 0
|
|
case 1:
|
|
z.Flags.Z = z.C&(1<<bitNumber) == 0
|
|
case 2:
|
|
z.Flags.Z = z.D&(1<<bitNumber) == 0
|
|
case 3:
|
|
z.Flags.Z = z.E&(1<<bitNumber) == 0
|
|
case 4:
|
|
z.Flags.Z = z.H&(1<<bitNumber) == 0
|
|
case 5:
|
|
z.Flags.Z = z.L&(1<<bitNumber) == 0
|
|
case 6:
|
|
z.Flags.Z = z.core.MemRead(z.hl())&(1<<bitNumber) == 0
|
|
default:
|
|
z.Flags.Z = z.A&(1<<bitNumber) == 0
|
|
}
|
|
z.Flags.N = false
|
|
z.Flags.H = true
|
|
z.Flags.P = z.Flags.Z
|
|
z.Flags.S = (bitNumber == 7) && !z.Flags.Z
|
|
// For the BIT n, (HL) instruction, the X and Y flags are obtained
|
|
// from what is apparently an internal temporary register used for
|
|
// some of the 16-bit arithmetic instructions.
|
|
// I haven't implemented that register here,
|
|
// so for now we'll set X and Y the same way for every BIT opcode,
|
|
// which means that they will usually be wrong for BIT n, (HL).
|
|
z.Flags.Y = (bitNumber == 5) && !z.Flags.Z
|
|
z.Flags.X = (bitNumber == 3) && !z.Flags.Z
|
|
} else if opcode < 0xC0 {
|
|
// RES instructions
|
|
negMask := byte(^(1 << bitNumber))
|
|
switch regCode {
|
|
case 0:
|
|
z.B &= negMask
|
|
case 1:
|
|
z.C &= negMask
|
|
case 2:
|
|
z.D &= negMask
|
|
case 3:
|
|
z.E &= negMask
|
|
case 4:
|
|
z.H &= negMask
|
|
case 5:
|
|
z.L &= negMask
|
|
case 6:
|
|
z.core.MemWrite(z.hl(), z.core.MemRead(z.hl())&negMask)
|
|
default:
|
|
z.A &= negMask
|
|
}
|
|
} else {
|
|
// SET instructions
|
|
mask := byte(1 << bitNumber)
|
|
switch regCode {
|
|
case 0:
|
|
z.B |= mask
|
|
case 1:
|
|
z.C |= mask
|
|
case 2:
|
|
z.D |= mask
|
|
case 3:
|
|
z.E |= mask
|
|
case 4:
|
|
z.H |= mask
|
|
case 5:
|
|
z.L |= mask
|
|
case 6:
|
|
z.core.MemWrite(z.hl(), z.core.MemRead(z.hl())|mask)
|
|
default:
|
|
z.A |= mask
|
|
}
|
|
}
|
|
z.CycleCounter += CycleCountsCb[opcode]
|
|
}
|