aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/cpu/opcodes/Loads16Bit.kt
blob: 830f6ab98b10d842ce8750ff4d96ede86a9875c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package cpu.opcodes

import cpu.Operation
import cpu.Registers
import cpu.Registers.Flag
import ram.Ram
import BitManipulation as bm

// 8-Bit Loads
var loads16Bit = mapOf(

  0x01 to Operation("LD BC,nn", 2, 12, {r, _, a -> r.BC = bm.argsToWord(a)}),
  0x11 to Operation("LD DE,nn", 2, 12, {r, _, a -> r.DE = bm.argsToWord(a)}),
  0x21 to Operation("LD HL,nn", 2, 12, {r, _, a -> r.HL = bm.argsToWord(a)}),
  0x31 to Operation("LD SP,nn", 2, 12, {r, _, a -> r.SP = bm.argsToWord(a)}),

  0xF9 to Operation("LD SP,HL", 0, 8, {r, _, _ -> r.SP = r.HL}),

  0xF8 to Operation("LDHL SP,n", 1, 12, {r, _, a ->

    // https://stackoverflow.com/questions/5159603/gbz80-how-does-ld-hl-spe-affect-h-and-c-flags
    // the carry flag is set if there's an overflow from the 7th to 8th bit.
    // the half carry flag is set if there's an overflow from the 3rd into the 4th bit.
    r.clearFlags()

    val absoluteValue = bm.getAbsoluteValue(a[0])

    if (bm.isSignedBitNegative(a[0])) {
      r.setFlagFromBool(Flag.HALF_CARRY, r.SP and 0x0F < absoluteValue and 0x0F)
      r.setFlagFromBool(Flag.CARRY,r.SP and 0xFF < absoluteValue)
      r.HL = r.SP - absoluteValue

    } else {
      r.setFlagFromBool(Flag.HALF_CARRY,(r.SP and 0x0F) + (absoluteValue and 0x0F) > 0x0F)
      r.setFlagFromBool(Flag.CARRY,(r.SP and 0xFF) + absoluteValue > 0xFF)
      r.HL = r.SP + absoluteValue
    }

  }),
  0x08 to Operation("LD (nn),SP", 2, 20, {r, m, a ->
    m.writeByte(bm.argsToWord(a), bm.getLsb(r.SP))
    m.writeByte(bm.argsToWord(a) + 1, bm.getMsb(r.SP))
    // TODO - not sure if the lsb/msb order is right here
  }),

  0xF5 to Operation("PUSH AF", 0, 16, {r, m, _ ->
    m.writeByte(r.decrementAndGetSP(), bm.getMsb(r.AF))
    m.writeByte(r.decrementAndGetSP(), bm.getLsb(r.AF))
  }),
  0xC5 to Operation("PUSH BC", 0, 16, {r, m, _ ->
    m.writeByte(r.decrementAndGetSP(), bm.getMsb(r.BC))
    m.writeByte(r.decrementAndGetSP(), bm.getLsb(r.BC))
  }),
  0xD5 to Operation("PUSH DE", 0, 16, {r, m, _ ->
    m.writeByte(r.decrementAndGetSP(), bm.getMsb(r.DE))
    m.writeByte(r.decrementAndGetSP(), bm.getLsb(r.DE))
  }),
  0xE5 to Operation("PUSH HL", 0, 16, {r, m, _ ->
    m.writeByte(r.decrementAndGetSP(), bm.getMsb(r.HL))
    m.writeByte(r.decrementAndGetSP(), bm.getLsb(r.HL))
  }),

  0xF1 to Operation("POP AF", 0, 12, {r, m, _ -> r.AF = pop(r, m)}),
  0xC1 to Operation("POP BC", 0, 12, {r, m, _ -> r.BC = pop(r, m)}),
  0xD1 to Operation("POP DE", 0, 12, {r, m, _ -> r.DE = pop(r, m)}),
  0xE1 to Operation("POP HL", 0, 12, {r, m, _ -> r.HL = pop(r, m)})

)

fun pop(r: Registers, m: Ram): Int {
  val lsb = m.readByte(r.getAndIncrementSP())
  val msb = m.readByte(r.getAndIncrementSP())
  return bm.bytesToWord(msb, lsb)
}