Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Jessica Hawkwell
/
kcpu
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
2
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 78af4d11
authored
Oct 01, 2017
by
Jessica Hawkwell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
started preliminary support for interrupts, stacks, and function calls
1 parent
c44caf9d
Pipeline
#211
passed
in 1 minute 8 seconds
Changes
21
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
254 additions
and
168 deletions
.gitignore
src/main/java/me/felinewith/kcpu/KBoard.java
src/main/java/me/felinewith/kcpu/Kasm.java
src/main/java/me/felinewith/kcpu/Kcpu.java
src/main/java/me/felinewith/kcpu/Kemulator.java
src/main/java/me/felinewith/kcpu/hardware/Kmcu.java
src/main/java/me/felinewith/kcpu/interfaces/IDevice.java
src/main/java/me/felinewith/kcpu/interfaces/IMemory.java
src/main/java/me/felinewith/kcpu/memory/BootRom.java
src/main/java/me/felinewith/kcpu/memory/Buffer.java
src/main/java/me/felinewith/kcpu/opcodes/Memory.java
src/main/java/me/felinewith/kcpu/opcodes/OpDirector.java
src/main/java/me/felinewith/kcpu/util/BaseDevice.java
src/main/java/me/felinewith/kcpu/util/BaseMemory.java
src/main/java/me/felinewith/kcpu/util/CPUStoppedException.java
src/main/java/me/felinewith/kcpu/util/HardwareExec.java
src/main/java/me/felinewith/kcpu/util/HardwareMemIrq.java
src/main/java/me/felinewith/kcpu/util/HardwareSendIrq.java → src/main/java/me/felinewith/kcpu/util/HardwareRecvIrq.java
src/main/java/me/felinewith/kcpu/util/helpers/ValueHelper.java
src/main/java/me/felinewith/kcpu/util/helpers/ValueType.java
test.kasm
.gitignore
View file @
78af4d1
# project-specific stuffs
*.mem
*.mem
.txt
*.bin
*.kc
...
...
src/main/java/me/felinewith/kcpu/KBoard.java
View file @
78af4d1
...
...
@@ -13,8 +13,9 @@ import me.felinewith.kcpu.hardware.Kmcu;
import
me.felinewith.kcpu.interfaces.IDevice
;
import
me.felinewith.kcpu.interfaces.IMemory
;
import
me.felinewith.kcpu.util.BaseDevice
;
import
me.felinewith.kcpu.util.
HardwareExec
;
import
me.felinewith.kcpu.util.
CPUStoppedException
;
import
me.felinewith.kcpu.util.HardwareMemIrq
;
import
me.felinewith.kcpu.util.HardwareRecvIrq
;
/**
*
...
...
@@ -56,45 +57,66 @@ public class KBoard extends BaseDevice implements IMemory {
System
.
out
.
println
(
"CPU up..."
);
while
(
cpu
.
workCycle
()
!=
0xff
)
{
Thread
.
yield
();
try
{
while
(
true
)
{
cpu
.
workCycle
();
Thread
.
yield
();
}
}
catch
(
CPUStoppedException
x
)
{}
System
.
err
.
println
(
"CPU Stopped [zpwr]"
);
tpe
.
shutdown
();
System
.
err
.
println
(
"Timers stopped"
);
int
a
;
for
(
a
=
0
;
a
<=
0xf
;
a
++)
{
if
(
devices
[
a
]
!=
null
)
{
devices
[
a
].
powerOff
();
System
.
err
.
println
(
String
.
format
(
"device %x stopped"
,
a
));
}
if
(
memDevs
[
a
]
!=
null
)
{
memDevs
[
a
].
powerOff
();
System
.
err
.
println
(
String
.
format
(
"memdev %x stopped"
,
a
));
}
}
dumpEverything
();
}
@Override
public
void
memIrq
(
short
addr
)
{
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
short
dev
=
checkDevice
(
addr
);
short
rdev
=
(
short
)(
0x0f
&
dev
);
if
(
dev
==
0x7f
)
{
devices
[
0
].
memIrq
(
addr
);
}
StackTraceElement
ste
=
Thread
.
currentThread
().
getStackTrace
()[
1
];
String
className
=
ste
.
getClassName
();
int
sendIrq
=
16
;
int
a
;
for
(
a
=
0
;
a
<
16
;
a
++)
{
if
(
devices
[
a
].
getClass
().
getCanonicalName
().
equals
(
className
))
{
sendIrq
=
a
;
break
;
}
}
if
(
dev
==
0x7f
)
{
devices
[
0
].
memIrq
(
addr
,
(
byte
)
sendIrq
);
}
else
if
(
dev
<=
0x0f
)
{
short
devOff
=
deviceMaps
[
rdev
].
getOffset
();
short
devAddr
=
(
short
)(
addr
-
devOff
);
tpe
.
execute
(
new
HardwareMemIrq
(
devices
[
rdev
],
devAddr
));
tpe
.
execute
(
new
HardwareMemIrq
(
devices
[
rdev
],
devAddr
,
(
byte
)
sendIrq
));
}
else
if
(
0x10
<=
dev
&&
dev
<=
0x1f
)
{
short
devOff
=
memDevMaps
[
rdev
].
getOffset
();
short
devAddr
=
(
short
)(
addr
-
devOff
);
tpe
.
execute
(
new
HardwareMemIrq
(
memDevs
[
rdev
],
devAddr
));
tpe
.
execute
(
new
HardwareMemIrq
(
memDevs
[
rdev
],
devAddr
,
(
byte
)
sendIrq
));
}
}
@Override
public
void
sendIrq
(
byte
irq
)
{
if
(
irq
>=
16
)
{
return
;
}
if
(
devices
[
irq
]
!=
null
)
{
tpe
.
execute
(
new
HardwareExec
(
devices
[
irq
]));
}
StackTraceElement
ste
=
Thread
.
currentThread
().
getStackTrace
()[
1
];
String
className
=
ste
.
getClassName
();
int
sendIrq
=
16
;
int
a
;
for
(
a
=
0
;
a
<
16
;
a
++)
{
if
(
devices
[
a
].
getClass
().
getCanonicalName
().
equals
(
className
))
{
sendIrq
=
a
;
break
;
}
}
if
(
devices
[
irq
]
!=
null
)
{
tpe
.
execute
(
new
HardwareRecvIrq
(
devices
[
irq
],
(
byte
)
sendIrq
));
}
}
@Override
public
short
length
()
{
return
(
short
)
memory
.
length
;
};
...
...
@@ -233,9 +255,6 @@ public class KBoard extends BaseDevice implements IMemory {
}
}
@Override
public
void
exec
()
{
}
public
void
dumpEverything
()
{
dumpMemory
(
"system"
,
memory
);
int
a
;
...
...
@@ -256,7 +275,7 @@ public class KBoard extends BaseDevice implements IMemory {
dumpMemory
(
filename
,
temp
);
}
public
void
dumpMemory
(
String
filename
,
byte
[]
mem
)
{
File
f
=
new
File
(
filename
.
concat
(
".mem"
));
File
f
=
new
File
(
filename
.
concat
(
".mem
.txt
"
));
try
{
System
.
out
.
println
(
String
.
format
(
"Writing %s"
,
f
.
getCanonicalPath
()));
}
catch
(
IOException
x
)
{}
try
(
FileWriter
fw
=
new
FileWriter
(
f
))
{
int
max
=
mem
.
length
;
...
...
src/main/java/me/felinewith/kcpu/Kasm.java
View file @
78af4d1
This diff is collapsed.
Click to expand it.
src/main/java/me/felinewith/kcpu/Kcpu.java
View file @
78af4d1
package
me
.
felinewith
.
kcpu
;
import
java.io.PrintStream
;
import
java.util.Arrays
;
import
me.felinewith.kcpu.interfaces.IMemory
;
import
me.felinewith.kcpu.opcodes.OpDirector
;
import
me.felinewith.kcpu.util.BaseDevice
;
import
me.felinewith.kcpu.util.CPUStoppedException
;
import
me.felinewith.kcpu.util.Converter
;
import
me.felinewith.kcpu.util.helpers.MemHelper
;
import
me.felinewith.kcpu.util.helpers.ValueHelper
;
import
me.felinewith.kcpu.util.helpers.ValueType
;
...
...
@@ -42,9 +45,20 @@ public class Kcpu extends BaseDevice {
short
[]
registers
;
private
KBoard
kboard
;
Thread
initThread
;
public
Kcpu
(
KBoard
system
)
{
memory
=
new
byte
[
0x0800
];
/**
* memory ranges:
* 0x0000 - 0x00ff : data stack
* 0x0100 - 0x017f : pc stack (return stack)
* 0x0180 - 0x019f : interrupt vectors
* 0x0120 : data stack pointer
* 0x0122 : pc stack pointer
* 0x0124 ~ unused
* 0x01ff : interrupt (boolean value)
*/
memory
=
new
byte
[
0x0200
];
name
=
"Kcpu"
;
settings
=
new
short
[
6
];
kboard
=
system
;
...
...
@@ -54,30 +68,45 @@ public class Kcpu extends BaseDevice {
}
@Override
public
void
init
(
IMemory
system
)
{
initThread
=
Thread
.
currentThread
();
setOuter
(
System
.
err
);
}
@Override
public
void
exec
()
{
workCycle
();
}
// need to prevent other devices from writing to CPU internals
@Override
public
void
write
(
short
offset
,
byte
data
)
{
}
@Override
public
byte
read
(
short
addr
)
{
if
(
(
0xffff
&
addr
)
>
length
()
)
{
return
(
byte
)
0xff
;
}
return
memory
[
0xffff
&
addr
];
}
@Override
public
void
recvIrq
(
byte
irq
)
{
synchronized
(
initThread
)
{
short
[]
regs
=
Arrays
.
copyOf
(
registers
,
registers
.
length
);
short
counter
=
pc
;
if
(
Thread
.
currentThread
().
getId
()
!=
initThread
.
getId
())
{
initThread
.
interrupt
();
regs
=
Arrays
.
copyOf
(
registers
,
registers
.
length
);
counter
=
pc
;
}
@Override
public
void
write
(
short
offset
,
byte
data
)
{
}
@Override
public
void
copy
(
short
addrSrc
,
short
addrDest
,
IMemory
dest
)
{
}
short
start
=
(
short
)((
irq
*
2
)
+
0x0180
);
pc
=
Converter
.
bytes2short
(
new
byte
[]{
memory
[
start
],
memory
[
start
+
1
]});
try
{
while
(
true
)
{
workCycle
();
Thread
.
yield
();
}
}
catch
(
CPUStoppedException
x
)
{}
@Override
public
void
memIrq
(
short
addr
)
{
if
(
0
<=
addr
&&
addr
<=
memory
.
length
)
{
exec
();
}
if
(
Thread
.
currentThread
().
getId
()
!=
initThread
.
getId
())
{
registers
=
Arrays
.
copyOf
(
regs
,
regs
.
length
);
pc
=
counter
;
initThread
.
notify
();
}
}
}
public
int
workCycle
()
{
public
void
workCycle
()
throws
CPUStoppedException
{
if
(
pc
>=
0xfff0
)
{
pc
=
0
;
}
short
inst
=
MemHelper
.
readShort
(
pc
,
kboard
);
short
ref
=
MemHelper
.
readShort
(
pc
+
2
,
kboard
);
short
[]
values
=
new
short
[
4
]
;
if
((
0xffff
&
inst
)
==
0xff
ff
){
log
ln
(
"Break!
"
);
short
[]
values
=
new
short
[
]{(
short
)
0
,
(
short
)
1
,
(
short
)
2
,
(
short
)
3
}
;
if
((
0xffff
&
inst
)
==
0xff
1b
){
log
(
"
"
);
}
switch
(
0x0700
&
ref
)
{
case
0x0700
:
case
0x0600
:
case
0x0500
:
...
...
@@ -96,8 +125,20 @@ public class Kcpu extends BaseDevice {
}
log
(
"%04x : [%10s] %04x ->"
,
pc
,
((
od
==
null
)?
"nop"
:
od
.
name
()),
ref
);
log
(
" %04x %04x %04x %04x "
,
registers
[
0
],
registers
[
1
],
registers
[
2
],
registers
[
3
]);
log
(
" %04x %04x %04x %04x\t\t"
,
registers
[
0
],
registers
[
1
],
registers
[
2
],
registers
[
3
]);
// bring up the program counter
if
(
od
==
null
)
{
pc
+=
12
;
return
;
}
// inc if nop
pc
+=
4
;
pc
+=
(((
0x0700
&
ref
)
>>
8
)
*
2
);
// this works because the value starts counting at 1
switch
(
0x0700
&
ref
)
{
case
0x0000
:
ref
+=
ValueType
.
R
.
getValue
();
case
0x0100
:
ref
+=
(
ValueType
.
R
.
getValue
()
<<
2
);
case
0x0200
:
ref
+=
(
ValueType
.
R
.
getValue
()
<<
4
);
case
0x0300
:
ref
+=
(
ValueType
.
R
.
getValue
()
<<
6
);
}
if
((
0x0700
&
ref
)
>=
0x0100
)
{
log
(
" %2s.%04x"
,
ValueType
.
valueOf
(
ref
,
0
),
values
[
0
]);
}
if
((
0x0700
&
ref
)
>=
0x0200
)
{
log
(
" %2s.%04x"
,
ValueType
.
valueOf
(
ref
,
1
),
values
[
1
]);
}
...
...
@@ -105,72 +146,65 @@ public class Kcpu extends BaseDevice {
if
((
0x0700
&
ref
)
>=
0x0400
)
{
log
(
" %2s.%04x"
,
ValueType
.
valueOf
(
ref
,
3
),
values
[
3
]);
}
logln
(
""
);
if
(
od
==
null
)
{
pc
+=
12
;
return
0
;
}
// inc if nop
pc
+=
4
;
pc
+=
(((
0x0700
&
ref
)
>>
8
)
*
2
);
if
(
od
.
hasHandler
()
)
{
registers
=
od
.
call
(
pc
,
ref
,
registers
,
values
,
kboard
);
return
0
;
return
;
}
short
data
=
ValueHelper
.
readShort
(
0
,
ref
,
registers
,
values
,
kboard
);
switch
(
od
)
{
// device management
case
DEVA:
registers
[
0
]
=
kboard
.
checkDevice
(
data
);
return
0
;
case
DEVD:
kboard
.
detachDevice
(
data
);
return
0
;
case
DEVA:
registers
[
0
]
=
kboard
.
checkDevice
(
data
);
return
;
case
DEVD:
kboard
.
detachDevice
(
data
);
return
;
case
DEVM:
kboard
.
setDeviceRange
(
data
,
ValueHelper
.
readShort
(
1
,
ref
,
registers
,
values
,
kboard
));
return
0
;
return
;
case
DEVP:
KMemoryRange
kmr
=
kboard
.
getDeviceRange
(
data
);
registers
[
0
]
=
kmr
.
getOffset
();
registers
[
1
]
=
kmr
.
getLength
();
return
0
;
return
;
// interrupts
case
IRQD:
kboard
.
sendIrq
((
byte
)(
0x000f
&
data
));
return
0
;
case
IRQM:
kboard
.
memIrq
(
data
);
return
0
;
case
IRQD:
kboard
.
sendIrq
((
byte
)(
0x000f
&
data
));
return
;
case
IRQM:
kboard
.
memIrq
(
data
,
(
byte
)
0
);
return
;
// jumps
case
JMP:
pc
=
(
short
)(
pc
+
(
0xffff
&
data
));
return
0
;
case
JMPA:
pc
=
data
;
return
0
;
case
JMPD:
pc
=
(
short
)(
pc
-
(
0xffff
&
data
));
return
0
;
case
JMP:
case
JMPU:
pc
=
(
short
)(
pc
+
(
0xffff
&
data
));
return
;
case
JMPA:
pc
=
data
;
return
;
case
JMPD:
pc
=
(
short
)(
pc
-
(
0xffff
&
data
));
return
;
case
GPC:
registers
=
ValueHelper
.
writeShort
(
0
,
ref
,
registers
,
values
,
kboard
,
pc
)
;
return
0
;
case
ZPWR:
return
0xff
;
registers
[
0
]
=
pc
;
return
;
case
ZPWR:
throw
new
CPUStoppedException
(
"zpwr"
)
;
}
short
data2
=
ValueHelper
.
readShort
(
1
,
ref
,
registers
,
values
,
kboard
);
short
data3
=
ValueHelper
.
readShort
(
2
,
ref
,
registers
,
values
,
kboard
);
switch
(
od
)
{
// conditionals
case
JE:
if
(
data
==
data2
)
{
pc
+=
data3
;
}
return
0
;
case
JAE:
if
(
data
==
data2
)
{
pc
=
data3
;
}
return
0
;
case
JDE:
if
(
data
==
data2
)
{
pc
-=
data3
;
}
return
0
;
case
JG:
if
(
data
>
data2
)
{
pc
+=
data3
;
}
return
0
;
case
JAG:
if
(
data
>
data2
)
{
pc
=
data3
;
}
return
0
;
case
JDG:
if
(
data
>
data2
)
{
pc
-=
data3
;
}
return
0
;
case
JL:
if
(
data
<
data2
)
{
pc
+=
data3
;
}
return
0
;
case
JAL:
if
(
data
<
data2
)
{
pc
=
data3
;
}
return
0
;
case
JDL:
if
(
data
<
data2
)
{
pc
-=
data3
;
}
return
0
;
case
JGE:
if
(
data
>=
data2
)
{
pc
+=
data3
;
}
return
0
;
case
JAGE:
if
(
data
>=
data2
)
{
pc
=
data3
;
}
return
0
;
case
JDGE:
if
(
data
>=
data2
)
{
pc
-=
data3
;
}
return
0
;
case
JLE:
if
(
data
<=
data2
)
{
pc
+=
data3
;
}
return
0
;
case
JALE:
if
(
data
<=
data2
)
{
pc
=
data3
;
}
return
0
;
case
JDLE:
if
(
data
<=
data2
)
{
pc
-=
data3
;
}
return
0
;
case
JE:
if
(
data
==
data2
)
{
pc
+=
data3
;
}
return
;
case
JAE:
if
(
data
==
data2
)
{
pc
=
data3
;
}
return
;
case
JDE:
if
(
data
==
data2
)
{
pc
-=
data3
;
}
return
;
case
JG:
if
(
data
>
data2
)
{
pc
+=
data3
;
}
return
;
case
JAG:
if
(
data
>
data2
)
{
pc
=
data3
;
}
return
;
case
JDG:
if
(
data
>
data2
)
{
pc
-=
data3
;
}
return
;
case
JL:
if
(
data
<
data2
)
{
pc
+=
data3
;
}
return
;
case
JAL:
if
(
data
<
data2
)
{
pc
=
data3
;
}
return
;
case
JDL:
if
(
data
<
data2
)
{
pc
-=
data3
;
}
return
;
case
JGE:
if
(
data
>=
data2
)
{
pc
+=
data3
;
}
return
;
case
JAGE:
if
(
data
>=
data2
)
{
pc
=
data3
;
}
return
;
case
JDGE:
if
(
data
>=
data2
)
{
pc
-=
data3
;
}
return
;
case
JLE:
if
(
data
<=
data2
)
{
pc
+=
data3
;
}
return
;
case
JALE:
if
(
data
<=
data2
)
{
pc
=
data3
;
}
return
;
case
JDLE:
if
(
data
<=
data2
)
{
pc
-=
data3
;
}
return
;
case
VCMP:
registers
[
0
]
=
0
;
if
(
data
!=
data2
)
{
registers
[
0
]
+=
0x0001
;
}
if
(
data
>=
data2
)
{
registers
[
0
]
+=
0x0002
;
}
if
(
data
==
data2
)
{
registers
[
0
]
+=
0x0004
;
}
if
(
data
<=
data2
)
{
registers
[
0
]
+=
0x0008
;
}
return
0
;
}
return
0
;
}
}
src/main/java/me/felinewith/kcpu/Kemulator.java
View file @
78af4d1
...
...
@@ -30,7 +30,7 @@ public class Kemulator {
ArrayList
<
Option
>
option
=
new
ArrayList
<>();
option
.
add
(
Option
.
builder
(
"b"
)
.
longOpt
(
"bootrom"
)
.
argName
(
"bootrom
.kc
"
)
.
argName
(
"bootrom"
)
.
hasArg
()
.
numberOfArgs
(
8
)
.
build
()
...
...
src/main/java/me/felinewith/kcpu/hardware/Kmcu.java
View file @
78af4d1
package
me
.
felinewith
.
kcpu
.
hardware
;
import
me.felinewith.kcpu.hardware.kmcu.KmcuOp
;
import
java.io.PrintStream
;
import
java.util.Arrays
;
import
me.felinewith.kcpu.
util.Converter
;
import
me.felinewith.kcpu.
hardware.kmcu.KmcuOp
;
import
me.felinewith.kcpu.util.BaseDevice
;
import
me.felinewith.kcpu.util.Converter
;
/**
*
...
...
@@ -38,11 +38,6 @@ public class Kmcu extends BaseDevice {
name
=
"Kmcp"
;
}
@Override
public
void
exec
()
{
workInit
((
short
)
0
);
workInit
((
short
)
1
);
}
private
void
workInit
(
short
setting
)
{
byte
[]
reg
;
if
(
setting
==
0
)
{
reg
=
Arrays
.
copyOfRange
(
memory
,
0
,
7
);
}
...
...
@@ -465,9 +460,15 @@ public class Kmcu extends BaseDevice {
return
output
;
}
@Override
public
void
memIrq
(
short
addr
)
{
if
(
0
<=
addr
&&
addr
<=
memory
.
length
)
{
exec
();
}
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
if
(
0
<=
addr
&&
addr
<=
memory
.
length
)
{
workInit
((
short
)
0
);
workInit
((
short
)
1
);
}
}
@Override
public
void
sendIrq
(
byte
irq
)
{
}
@Override
public
void
recvIrq
(
byte
irq
)
{
workInit
((
short
)
0
);
workInit
((
short
)
1
);
}
}
src/main/java/me/felinewith/kcpu/interfaces/IDevice.java
View file @
78af4d1
...
...
@@ -8,5 +8,5 @@ public interface IDevice extends IMemory {
public
void
init
(
IMemory
board
);
public
abstract
void
sendIrq
(
byte
irq
);
public
void
exec
(
);
public
abstract
void
recvIrq
(
byte
irq
);
}
src/main/java/me/felinewith/kcpu/interfaces/IMemory.java
View file @
78af4d1
...
...
@@ -8,8 +8,7 @@ public interface IMemory {
public
abstract
short
length
();
public
abstract
byte
read
(
short
addr
);
public
abstract
void
write
(
short
addr
,
byte
data
);
public
void
copy
(
short
addrSrc
,
short
addrDest
,
IMemory
dest
);
public
abstract
void
memIrq
(
short
addr
);
public
abstract
void
memIrq
(
short
addr
,
byte
irq
);
public
void
powerOff
();
}
src/main/java/me/felinewith/kcpu/memory/BootRom.java
View file @
78af4d1
...
...
@@ -6,6 +6,7 @@ import java.io.FileNotFoundException;
import
java.io.IOException
;
import
java.util.Arrays
;
import
me.felinewith.kcpu.Kasm
;
import
me.felinewith.kcpu.Kasm.KasmBuilder
;
import
me.felinewith.kcpu.util.BaseMemory
;
/**
...
...
@@ -15,42 +16,42 @@ import me.felinewith.kcpu.util.BaseMemory;
public
class
BootRom
extends
BaseMemory
{
private
short
writepos
;
private
short
prev
;
private
short
prev2
;
private
boolean
writable
;
public
BootRom
()
{
writepos
=
0
;
prev
=
0
;
prev2
=
0
;
writable
=
false
;
writable
=
true
;
memory
=
new
byte
[
0x1000
];
Arrays
.
fill
(
memory
,
(
byte
)
0xff
);
KasmBuilder
kb
=
Kasm
.
builder
();
kb
.
setBASEaddr
((
short
)
0x1000
);
kb
.
setVerbose
(
false
);
Kasm
kasm
=
kb
.
build
();
// hardcoding some bootrom
writeBytes
(
Kasm
.
compile
(
"movs $0 r2"
));
writeBytes
(
Kasm
.
compile
(
"add r0 16"
));
writeBytes
(
Kasm
.
compile
(
"add r2 1"
));
writeBytes
(
Kasm
.
compile
(
"movs $0 r2"
));
writeBytes
(
Kasm
.
compile
(
"jdl r0 512 22,16"
));
//writeBytes(kasm.compileSegment("movs $0 r2"));
kasm
.
compileSegment
(
"mark"
);
writeBytes
(
kasm
.
compileSegment
(
"add r0 16"
));
writeBytes
(
kasm
.
compileSegment
(
"add r2 1"
));
writeBytes
(
kasm
.
compileSegment
(
"movs $0 r2"
));
writeBytes
(
kasm
.
compileSegment
(
"jdl r0 512 mark"
));
//writeBytes(Kasm.compile("movs r0 0"));
//writeBytes(Kasm.compile("movs r1 0"));
//writeBytes(Kasm.compile("movs r2 0"));
//writeBytes(Kasm.compile("movs r3 0"));
writeBytes
(
Kasm
.
compile
(
"gpc %0300,16
"
));
writeBytes
(
Kasm
.
compile
(
"mov ff00,16 61,16"
));
writeBytes
(
Kasm
.
compile
(
"irqm ff01,16"
));
writeBytes
(
kasm
.
compileSegment
(
"gpc
"
));
writeBytes
(
kasm
.
compileSegment
(
"mov ff00,16 61,16"
));
writeBytes
(
kasm
.
compileSegment
(
"irqm ff01,16"
));
}
@Override
public
void
memIrq
(
short
addr
)
{
writable
=
((
prev2
==
0x4b63
)
&&
(
prev
==
0x7075
)
&&
(
addr
==
0x7f
));
if
((
0xff
&
prev
)
==
0
)
{
prev
+=
addr
;
}
else
if
((
0xff00
&
prev
)
==
0
)
{
prev
=
(
short
)(
prev
<<
8
);
prev
+=
addr
;
}
else
{
prev2
=
prev
;
}
}
// writable at the start, so smart ROMs can rewrite themselves to rearrange stuff
// useful for moving devices around the address space at boot-time
// then a simple program can write a device table into ROM space
// finally, send an interrupt to the ROM device to lock it
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
writable
=
false
;
}
@Override
public
void
write
(
short
addr
,
byte
data
)
{
if
(!
writable
)
{
return
;
}
...
...
src/main/java/me/felinewith/kcpu/memory/Buffer.java
View file @
78af4d1
...
...
@@ -40,7 +40,7 @@ public class Buffer extends BaseMemory {
bufout
=
new
OutputStreamWriter
(
stdout
);
}
@Override
public
void
memIrq
(
short
addr
)
{
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
short
a
;
short
value
;
if
(
addr
<=
0x0f
)
{
...
...
src/main/java/me/felinewith/kcpu/opcodes/Memory.java
View file @
78af4d1
package
me
.
felinewith
.
kcpu
.
opcodes
;
import
me.felinewith.kcpu.util.helpers.ValueHelper
;
import
java.util.Arrays
;
import
me.felinewith.kcpu.interfaces.IMemory
;
import
me.felinewith.kcpu.util.helpers.ValueHelper
;
/**
*
...
...
@@ -11,8 +11,9 @@ import me.felinewith.kcpu.interfaces.IMemory;
public
class
Memory
implements
IOpcodeHandler
{
@Override
public
short
[]
opcode
(
OpDirector
opcode
,
short
pc
,
short
ref
,
short
[]
regs
,
short
[]
values
,
IMemory
memory
)
{
short
data
;
short
[]
output
=
Arrays
.
copyOf
(
regs
,
regs
.
length
);
short
addr
=
ValueHelper
.
readShort
(
0
,
ref
,
output
,
values
,
memory
);
short
data
;
switch
(
opcode
)
{
case
MOV:
case
MOVB:
data
=
ValueHelper
.
readByte
(
1
,
ref
,
output
,
values
,
memory
);
...
...
src/main/java/me/felinewith/kcpu/opcodes/OpDirector.java
View file @
78af4d1
...
...
@@ -18,43 +18,59 @@ public enum OpDirector {
MOV
(
0x0010
,
Memory
.
class
,
"Alias for MOVB"
),
MOVB
(
0x0010
,
Memory
.
class
,
"dest value"
),
MOVS
(
0x0011
,
Memory
.
class
,
"dest value"
),
// stack manipulation
PUSH
(
0x1000
,
"value: push value to stack"
),
POP
(
0x1001
,
"pop value off stack"
),
CALL
(
0x1002
,
"addr: call function at address"
),
RET
(
0x1003
,
"return from function"
),
IRET
(
0x10f0
,
"return from interrupt state (does nothing in normal mode)"
),
// interrupt vector management
IVEC
(
0x10f1
,
"irq addr: set function address for interrupt irq"
),
// cpu stuffies
DEVA
(
0xff00
,
"
n0; get device at address n0
"
),
// get device port from address
DEVD
(
0xff01
,
"
n0: detach device on port n0
"
),
// detach device
DEVM
(
0xff02
,
"
n0 n1: relocate device n0 to address n1
"
),
// relocate device
DEVP
(
0x1003
,
"
n0: get device address for device on port n0
"
),
// get device address from port
DEVA
(
0xff00
,
"
addr; get device at address
"
),
// get device port from address
DEVD
(
0xff01
,
"
port: detach device on port
"
),
// detach device
DEVM
(
0xff02
,
"
port newaddr: relocate device to address
"
),
// relocate device
DEVP
(
0x1003
,
"
port: get device address for device on port
"
),
// get device address from port
IRQD
(
0xff10
,
"n0: send interrupt to port n0"
),
// interrupt to port
IRQM
(
0xff11
,
"n0: send interrupt to memory address n0"
),
// interrupt to memory
// interrupts
IRQD
(
0xff10
,
"port: send interrupt to port"
),
// interrupt to port
IRQM
(
0xff11
,
"addr: send interrupt to memory address"
),
// interrupt to memory
// jumps
JMP
(
0xff18
,
"Alias of JMPU"
),
// jump up
JMPU
(
0xff18
,
"
n0
: jump up n0 addresses"
),
JMPA
(
0xff19
,
"
n0
: jump to address n0"
),
// jump absolute addr
JMPD
(
0xff1a
,
"
n0
: jump down n0 addresses"
),
// jump down
JMPU
(
0xff18
,
"
addr
: jump up n0 addresses"
),
JMPA
(
0xff19
,
"
addr
: jump to address n0"
),
// jump absolute addr
JMPD
(
0xff1a
,
"
addr
: jump down n0 addresses"
),
// jump down
GPC
(
0xff1b
,
"write instruction pointer"
),
// get instruction pointer
// comparisson jumps
JE
(
0xff20
,
"Alias of JUE"
),
// jump if =
JUE
(
0xff20
,
"n0 n1
n2
: jump if n0 == n1, see JMPU"
),
JAE
(
0xff21
,
"n0 n1
n2
: jump if n0 == n1, see JMPA"
),
JDE
(
0xff22
,
"n0 n1
n2
: jump if n0 == n1, see JMPD"
),
JUE
(
0xff20
,
"n0 n1
addr
: jump if n0 == n1, see JMPU"
),
JAE
(
0xff21
,
"n0 n1
addr
: jump if n0 == n1, see JMPA"
),
JDE
(
0xff22
,
"n0 n1
addr
: jump if n0 == n1, see JMPD"
),
JG
(
0xff23
,
"Alias of JUG"
),
// jump if >
JUG
(
0xff23
,
"n0 n1
n2
: jump if n0 > n1, see JMPU"
),
JAG
(
0xff24
,
"n0 n1
n2
: jump if n0 > n1, see JMPA"
),
JDG
(
0xff25
,
"n0 n1
n2
: jump if n0 > n1, see JMPD"
),
JUG
(
0xff23
,
"n0 n1
addr
: jump if n0 > n1, see JMPU"
),
JAG
(
0xff24
,
"n0 n1
addr
: jump if n0 > n1, see JMPA"
),
JDG
(
0xff25
,
"n0 n1
addr
: jump if n0 > n1, see JMPD"
),
JL
(
0xff26
,
"Alias of JUL"
),
// jump if <
JUL
(
0xff26
,
"n0 n1
n2
: jump if n0 < n1, see JMPU"
),
JAL
(
0xff27
,
"n0 n1
n2
: jump if n0 < n1, see JMPA"
),
JDL
(
0xff28
,
"n0 n1
n2
: jump if n0 < n1, see JMPD"
),
JUL
(
0xff26
,
"n0 n1
addr
: jump if n0 < n1, see JMPU"
),
JAL
(
0xff27
,
"n0 n1
addr
: jump if n0 < n1, see JMPA"
),
JDL
(
0xff28
,
"n0 n1
addr
: jump if n0 < n1, see JMPD"
),
JGE
(
0xff29
,
"Alias of JUGE"
),
// jump if >=
JUGE
(
0xff29
,
"n0 n1
n2
: jump if n0 >= n1, see JMPU"
),
JAGE
(
0xff2a
,
"n0 n1
n2
: jump if n0 >= n1, see JMPA"
),
JDGE
(
0xff2b
,
"n0 n1
n2
: jump if n0 >= n1, see JMPD"
),
JUGE
(
0xff29
,
"n0 n1
addr
: jump if n0 >= n1, see JMPU"
),
JAGE
(
0xff2a
,
"n0 n1
addr
: jump if n0 >= n1, see JMPA"
),
JDGE
(
0xff2b
,
"n0 n1
addr
: jump if n0 >= n1, see JMPD"
),
JLE
(
0xff2c
,
"Alias of JULE"
),
// jump if <=
JULE
(
0xff2c
,
"n0 n1 n2: jump if n0 <= n1, see JMPU"
),
JALE
(
0xff2d
,
"n0 n1 n2: jump if n0 <= n1, see JMPA"
),
JDLE
(
0xff2e
,
"n0 n1 n2: jump if n0 <= n1, see JMPD"
),
JULE
(
0xff2c
,
"n0 n1 addr: jump if n0 <= n1, see JMPU"
),
JALE
(
0xff2d
,
"n0 n1 addr: jump if n0 <= n1, see JMPA"
),
JDLE
(
0xff2e
,
"n0 n1 addr: jump if n0 <= n1, see JMPD"
),
// value compare
VCMP
(
0xff2f
,
"n0 n1: performs multiple comparissons of n0 and n1"
),
// power
ZPWR
(
0xffff
,
"Power off"
),
// power off
;
...
...
src/main/java/me/felinewith/kcpu/util/BaseDevice.java
View file @
78af4d1
...
...
@@ -16,16 +16,13 @@ public abstract class BaseDevice extends BaseMemory implements IDevice {
board
=
system
;
}
@Override
public
void
memIrq
(
short
addr
)
{
if
(
0
<=
addr
&&
addr
<=
memory
.
length
)
{
exec
();
}
}
protected
void
sendIrq
()
{
int
addr
=
memory
.
length
-
1
;
sendIrq
(
memory
[
addr
]);
}
@Override
public
void
sendIrq
(
byte
irq
)
{
}
@Override
public
void
recvIrq
(
byte
irq
)
{
}
@Override
public
short
length
()
{
return
(
short
)
memory
.
length
;
}
...
...
src/main/java/me/felinewith/kcpu/util/BaseMemory.java
View file @
78af4d1
...
...
@@ -26,13 +26,7 @@ public abstract class BaseMemory implements IMemory {
memory
[
0xffff
&
addr
]
=
data
;
}
public
final
void
copy
(
int
addrSrc
,
int
addrDest
,
IMemory
dest
)
{
copy
((
short
)
addrSrc
,
(
short
)
addrDest
,
dest
);
}
@Override
public
void
copy
(
short
addrSrc
,
short
addrDest
,
IMemory
dest
)
{
if
(
(
0xffff
&
addrSrc
)
>
length
()
)
{
return
;
}
dest
.
write
(
addrDest
,
read
(
addrSrc
));
}
@Override
public
void
memIrq
(
short
addr
)
{
}
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
}
@Override
public
void
powerOff
()
{
}
}
src/main/java/me/felinewith/kcpu/util/CPUStoppedException.java
0 → 100644
View file @
78af4d1
package
me
.
felinewith
.
kcpu
.
util
;
/**
*
* @author jlhawkwell
*/
public
class
CPUStoppedException
extends
Exception
{
/**
* Creates a new instance of <code>CPUStoppedException</code> without detail message.
*/
public
CPUStoppedException
()
{
}
/**
* Constructs an instance of <code>CPUStoppedException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public
CPUStoppedException
(
String
msg
)
{
super
(
msg
);
}
}
src/main/java/me/felinewith/kcpu/util/HardwareExec.java
deleted
100644 → 0
View file @
c44caf9
package
me
.
felinewith
.
kcpu
.
util
;
import
java.util.TimerTask
;
import
me.felinewith.kcpu.interfaces.IDevice
;
/**
*
* @author jlhawkwell
*/
public
class
HardwareExec
extends
TimerTask
{
IDevice
id
;
public
HardwareExec
(
IDevice
device
)
{
id
=
device
;
}
@Override
public
void
run
()
{
id
.
exec
();
}
}
src/main/java/me/felinewith/kcpu/util/HardwareMemIrq.java
View file @
78af4d1
...
...
@@ -11,10 +11,15 @@ public class HardwareMemIrq extends TimerTask {
IMemory
id
;
short
a
;
byte
i
;
public
HardwareMemIrq
(
IMemory
device
,
short
addr
)
{
public
HardwareMemIrq
(
IMemory
device
,
short
addr
,
byte
irq
)
{
id
=
device
;
a
=
addr
;
i
=
irq
;
}
@Override
public
void
run
()
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"memIRQ-%02x-%x"
,
id
,
Thread
.
currentThread
().
getId
()
));
id
.
memIrq
(
a
,
i
);
}
@Override
public
void
run
()
{
id
.
memIrq
(
a
);
}
}
src/main/java/me/felinewith/kcpu/util/Hardware
Send
Irq.java
→
src/main/java/me/felinewith/kcpu/util/Hardware
Recv
Irq.java
View file @
78af4d1
...
...
@@ -7,14 +7,17 @@ import me.felinewith.kcpu.interfaces.IDevice;
*
* @author jlhawkwell
*/
public
class
Hardware
Send
Irq
extends
TimerTask
{
public
class
Hardware
Recv
Irq
extends
TimerTask
{
IDevice
id
;
byte
i
;
public
Hardware
Send
Irq
(
IDevice
device
,
byte
irq
)
{
public
Hardware
Recv
Irq
(
IDevice
device
,
byte
irq
)
{
id
=
device
;
i
=
irq
;
}
@Override
public
void
run
()
{
id
.
sendIrq
(
i
);
}
@Override
public
void
run
()
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"recvIRQ-%02x_%02x-%x"
,
id
,
i
,
Thread
.
currentThread
().
getId
()
));
id
.
recvIrq
(
i
);
}
}
src/main/java/me/felinewith/kcpu/util/helpers/ValueHelper.java
View file @
78af4d1
...
...
@@ -25,6 +25,7 @@ public class ValueHelper {
case
2
:
cref
=
(
short
)(
0x0030
&
ref
);
break
;
case
3
:
cref
=
(
short
)(
0x00c0
&
ref
);
break
;
}
switch
(
cref
)
{
case
0x0000
:
output
=
values
[
pos
];
break
;
case
0x0001
:
case
0x0004
:
case
0x0010
:
case
0x0040
:
...
...
@@ -55,10 +56,14 @@ public class ValueHelper {
case
2
:
cref
=
(
short
)(
0x0030
&
ref
);
break
;
case
3
:
cref
=
(
short
)(
0x00c0
&
ref
);
break
;
}
// short-circuit write to register if position isn't used in the instruction
if
(
pos
>
((
0x0f00
&
reg
)
>>
8
))
{
cref
=
1
;
}
switch
(
cref
)
{
case
0x0000
:
case
0x0001
:
case
0x0004
:
case
0x0010
:
case
0x0040
:
output
[
reg
]
=
data
;
break
;
case
0x0000
:
case
0x0002
:
case
0x0008
:
case
0x0020
:
case
0x0080
:
MemHelper
.
writeByte
(
values
[
pos
],
data
,
memory
);
break
;
case
0x0003
:
case
0x000c
:
case
0x0030
:
case
0x00c0
:
...
...
@@ -109,10 +114,16 @@ public class ValueHelper {
case
2
:
cref
=
(
short
)(
0x0030
&
ref
);
break
;
case
3
:
cref
=
(
short
)(
0x00c0
&
ref
);
break
;
}
// short-circuit write to register if position isn't used in the instruction
if
(
pos
>
((
0x0f00
&
ref
)
>>
8
))
{
cref
=
1
;
}
switch
(
cref
)
{
case
0x0000
:
case
0x0001
:
case
0x0004
:
case
0x0010
:
case
0x0040
:
output
[
reg
]
=
data
;
break
;
case
0x0000
:
case
0x0002
:
case
0x0008
:
case
0x0020
:
case
0x0080
:
MemHelper
.
writeShort
(
values
[
pos
],
data
,
memory
);
break
;
case
0x0003
:
case
0x000c
:
case
0x0030
:
case
0x00c0
:
...
...
src/main/java/me/felinewith/kcpu/util/helpers/ValueType.java
View file @
78af4d1
...
...
@@ -10,8 +10,8 @@ public enum ValueType {
AD
(
2
),
AR
(
3
);
in
t
t
;
private
ValueType
(
int
type
)
{
t
=
type
;
}
shor
t
t
;
private
ValueType
(
int
type
)
{
t
=
(
short
)
type
;
}
public
static
ValueType
valueOf
(
int
value
,
int
position
)
{
int
temp
=
value
>>
(
position
*
2
);
...
...
@@ -24,5 +24,5 @@ public enum ValueType {
}
return
D
;
}
public
in
t
getValue
()
{
return
t
;
}
public
shor
t
getValue
()
{
return
t
;
}
}
test.kasm
View file @
78af4d1
...
...
@@ -2,9 +2,9 @@ movs $0 r2
add r0 16
add r2 1
movs $0 r2
jdl r0 512 2a,16
jdl r0 512 2
0,16+
a,16
deva 0
deva 1
gpc
gpc %300,16
gpc %
100,16+
300,16
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment