-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpu.lua
executable file
·123 lines (116 loc) · 3.94 KB
/
cpu.lua
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
local bit = bit or require "bit32"
local path = (...):match("(.-)[^%.]+$")
local instructions = require(path .. '.instructions')
local cpu = {
inte = true,
ports = setmetatable({
internal = {
input = {},
output = {}
}
}, {
__index = function(tbl, index)
if type(tbl.internal.input[index]) == "function" then
return tbl.internal.input[index]()
else
return tbl.internal.input[index] or 0
end
end,
__newindex = function(tbl, index, value)
if type(tbl.internal.output[index]) == "function" then
tbl.internal.output[index](value)
end
end
}),
registers = setmetatable({
internal = {
a = 0,
b = 0,
c = 0,
d = 0,
e = 0,
h = 0,
l = 0,
sp = 0,
pc = 0,
status = {
c = false,
z = false,
n = false,
h = false,
p = false
}
}
}, {
__index = function(tbl, index)
if index == "bc" then
return bit.bor(bit.lshift(tbl.internal.b, 8), tbl.internal.c)
elseif index == "de" then
return bit.bor(bit.lshift(tbl.internal.d, 8), tbl.internal.e)
elseif index == "hl" then
return bit.bor(bit.lshift(tbl.internal.h, 8), tbl.internal.l)
elseif index == "psw" then
local f = tbl.status.n and 1 or 0
f = bit.lshift(f, 1)
f = bit.bor(f, tbl.status.z and 1 or 0)
f = bit.lshift(f, 1)
f = bit.lshift(f, 1)
f = bit.bor(f, tbl.status.h and 1 or 0)
f = bit.lshift(f, 1)
f = bit.lshift(f, 1)
f = bit.bor(f, tbl.status.p and 1 or 0)
f = bit.lshift(f, 1)
f = bit.bor(f, 1)
f = bit.lshift(f, 1)
f = bit.bor(f, tbl.status.c and 1 or 0)
return bit.bor(bit.lshift(tbl.internal.a, 8), f)
else
return tbl.internal[index]
end
end,
__newindex = function(tbl, index, value)
if index == "bc" then
tbl.internal.c = bit.band(value, 0xFF)
tbl.internal.b = bit.rshift(bit.band(value, 0xFF00), 8)
elseif index == "de" then
tbl.internal.e = bit.band(value, 0xFF)
tbl.internal.d = bit.rshift(bit.band(value, 0xFF00), 8)
elseif index == "hl" then
tbl.internal.l = bit.band(value, 0xFF)
tbl.internal.h = bit.rshift(bit.band(value, 0xFF00), 8)
elseif index == "sp" then
tbl.internal.sp = bit.band(value, 0xFFFF)
elseif index == "pc" then
tbl.internal.pc = bit.band(value, 0xFFFF)
elseif index == "psw" then
tbl.internal.a = bit.rshift(value, 8)
tbl.status.c = bit.band(value, 1) ~= 0
tbl.status.p = bit.band(value, 4) ~= 0
tbl.status.h = bit.band(value, 16) ~= 0
tbl.status.z = bit.band(value, 64) ~= 0
tbl.status.n = bit.band(value, 128) ~= 0
else
tbl.internal[index] = bit.band(value, 0xFF)
end
end
})
}
function cpu:init(bus)
self.bus = bus
instructions:init(self, bus)
end
function cpu:fetch()
local opcode = self.bus[self.registers.pc]
self.registers.pc = self.registers.pc + 1
return opcode
end
function cpu:decode(opcode)
return instructions.opcodes[opcode]
end
function cpu:execute(operation)
return instructions[operation.instruction](instructions, operation.op1, operation.op2, operation.imm)
end
function cpu:cycle()
return self:execute(self:decode(self:fetch()))
end
return cpu