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 adb54524
authored
Oct 01, 2017
by
Jessica Hawkwell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added 6 new instructions, had to restructure a bit to support interrupts
1 parent
88a0a581
Pipeline
#213
passed
in 1 minute 4 seconds
Changes
19
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
345 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/KcpuExceptions.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/BasicMath.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/FakeFuture.java
src/main/java/me/felinewith/kcpu/util/HardwareFinished.java
src/main/java/me/felinewith/kcpu/util/HardwareMemIrq.java
src/main/java/me/felinewith/kcpu/util/HardwareRecvIrq.java
.gitignore
View file @
adb5452
# project-specific stuffs
*.mem.txt
*.bin
*.mem.*
*.kc
# swap
...
...
src/main/java/me/felinewith/kcpu/KBoard.java
View file @
adb5452
...
...
@@ -6,14 +6,15 @@ import java.io.FileWriter;
import
java.io.IOException
;
import
java.nio.charset.Charset
;
import
java.util.Arrays
;
import
java.util.concurrent.LinkedBlockingQueue
;
import
java.util.concurrent.ThreadPoolExecutor
;
import
java.util.concurrent.TimeUnit
;
import
me.felinewith.kcpu.hardware.Kmcu
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
me.felinewith.kcpu.interfaces.IDevice
;
import
me.felinewith.kcpu.interfaces.IMemory
;
import
me.felinewith.kcpu.util.BaseDevice
;
import
me.felinewith.kcpu.util.CPUStoppedException
;
import
me.felinewith.kcpu.util.FakeFuture
;
import
me.felinewith.kcpu.util.HardwareFinished
;
import
me.felinewith.kcpu.util.HardwareMemIrq
;
import
me.felinewith.kcpu.util.HardwareRecvIrq
;
...
...
@@ -23,7 +24,7 @@ import me.felinewith.kcpu.util.HardwareRecvIrq;
*/
public
class
KBoard
extends
BaseDevice
implements
IMemory
{
final
ThreadPoolExecutor
tpe
;
final
ExecutorService
es
;
IDevice
[]
devices
;
KMemoryRange
[]
deviceMaps
;
...
...
@@ -35,7 +36,7 @@ public class KBoard extends BaseDevice implements IMemory {
Kcpu
cpu
;
public
KBoard
()
{
tpe
=
new
ThreadPoolExecutor
(
16
,
32
,
30
,
TimeUnit
.
SECONDS
,
new
LinkedBlockingQueue
<>(
16
)
);
es
=
Executors
.
newCachedThreadPool
(
);
memory
=
new
byte
[
0x010000
];
devices
=
new
IDevice
[
16
];
deviceMaps
=
new
KMemoryRange
[
16
];
...
...
@@ -48,24 +49,24 @@ public class KBoard extends BaseDevice implements IMemory {
public
void
init
()
{
cpu
=
new
Kcpu
(
this
);
attachDevice
(
0x8000
,
cpu
);
attachDevice
(
0x8800
,
new
Kmcu
());
//attachMemory(0, 0xff00, new Buffer());
//attachMemory(1, 0x1000, new BootRom());
System
.
out
.
println
(
"CPU up..."
);
logln
(
"CPU up..."
);
Future
f
=
new
FakeFuture
();
try
{
while
(
true
)
{
cpu
.
workCycle
();
Thread
.
yield
();
// we may have a program wait for an interrupt to finish
// we halt here so we don't clobber anything
if
(
f
.
isDone
())
{
f
=
cpu
.
workCycle
(
0
);
}
}
}
catch
(
CPUStoppedException
x
)
{}
System
.
err
.
println
(
"CPU Stopped [zpwr]"
);
tpe
.
shutdown
();
catch
(
CPUStoppedException
x
)
{
logln
(
"CPU Stopped: %s"
,
x
.
getMessage
());}
es
.
shutdown
();
while
(!
es
.
isTerminated
())
{
// slightly longer wait time here, just to give other threads a chance to quit
try
{
Thread
.
sleep
(
1
l
);
}
catch
(
InterruptedException
x
)
{
Thread
.
yield
();
}
}
int
a
;
for
(
a
=
0
;
a
<=
0xf
;
a
++)
{
if
(
devices
[
a
]
!=
null
)
{
...
...
@@ -78,13 +79,12 @@ public class KBoard extends BaseDevice implements IMemory {
dumpEverything
();
}
@Override
public
void
m
emIrq
(
short
addr
,
byte
irq
)
{
@Override
public
Future
<
HardwareFinished
>
sendM
emIrq
(
short
addr
,
byte
irq
)
{
short
dev
=
checkDevice
(
addr
);
short
rdev
=
(
short
)(
0x0f
&
dev
);
StackTraceElement
[]
stes
=
Thread
.
currentThread
().
getStackTrace
();
StackTraceElement
ste
=
stes
[
2
];
String
className
=
ste
.
getClassName
();
System
.
err
.
format
(
"\t\t%s\n"
,
ste
.
getClassName
());
int
sendIrq
=
16
;
int
a
;
for
(
a
=
0
;
a
<
16
;
a
++)
{
...
...
@@ -92,33 +92,41 @@ public class KBoard extends BaseDevice implements IMemory {
sendIrq
=
a
;
break
;
}
if
((
memDevs
[
a
]
!=
null
)
&&
memDevs
[
a
].
getClass
().
getCanonicalName
().
equals
(
className
))
{
sendIrq
=
0x10
+
a
;
break
;
}
}
if
(
dev
==
0x7f
)
{
devices
[
0
].
m
emIrq
(
addr
,
(
byte
)
sendIrq
);
}
if
(
dev
==
0x7f
)
{
devices
[
0
].
recvM
emIrq
(
addr
,
(
byte
)
sendIrq
);
}
else
if
(
dev
<=
0x0f
)
{
short
devOff
=
deviceMaps
[
rdev
].
getOffset
();
short
devAddr
=
(
short
)(
addr
-
devOff
);
tpe
.
execute
(
new
HardwareMemIrq
(
devices
[
rdev
],
devAddr
,
(
byte
)
sendIrq
));
return
es
.
submit
(
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
,
(
byte
)
sendIrq
));
return
es
.
submit
(
new
HardwareMemIrq
(
memDevs
[
rdev
],
devAddr
,
(
byte
)
sendIrq
));
}
return
new
FakeFuture
();
}
@Override
public
void
sendIrq
(
byte
irq
)
{
if
(
irq
>=
16
)
{
return
;
}
StackTraceElement
ste
=
Thread
.
currentThread
().
getStackTrace
()[
1
];
@Override
public
Future
<
HardwareFinished
>
sendIrq
(
byte
irq
)
{
if
(
irq
>=
16
)
{
return
super
.
sendIrq
(
irq
)
;
}
StackTraceElement
ste
=
Thread
.
currentThread
().
getStackTrace
()[
2
];
String
className
=
ste
.
getClassName
();
int
sendIrq
=
16
;
int
a
;
for
(
a
=
0
;
a
<
16
;
a
++)
{
if
(
devices
[
a
].
getClass
().
getCanonicalName
().
equals
(
className
))
{
if
(
(
devices
[
a
]
!=
null
)
&&
devices
[
a
].
getClass
().
getCanonicalName
().
equals
(
className
))
{
sendIrq
=
a
;
break
;
}
}
if
(
devices
[
irq
]
!=
null
)
{
tpe
.
execute
(
new
HardwareRecvIrq
(
devices
[
irq
],
(
byte
)
sendIrq
));
}
if
(
devices
[
irq
]
!=
null
)
{
return
es
.
submit
(
new
HardwareRecvIrq
(
devices
[
irq
],
(
byte
)
sendIrq
));
}
return
new
FakeFuture
();
}
@Override
public
short
length
()
{
return
(
short
)
memory
.
length
;
};
...
...
@@ -133,16 +141,16 @@ public class KBoard extends BaseDevice implements IMemory {
else
if
(
0x10
<=
dev
&&
dev
<=
0x1f
)
{
short
devOff
=
memDevMaps
[
rdev
].
getOffset
();
short
devAddr
=
(
short
)(
addr
-
devOff
);
return
memDevs
[
rdev
].
read
(
devAddr
);
synchronized
(
memory
)
{
return
memDevs
[
rdev
].
read
(
devAddr
);
}
}
return
memory
[
0xffff
&
addr
];
synchronized
(
memory
)
{
return
memory
[
0xffff
&
addr
];
}
}
@Override
public
void
write
(
short
addr
,
byte
data
)
{
short
dev
=
checkDevice
(
addr
);
System
.
err
.
printf
(
"\tWriting %2x to %04x\n
"
,
data
,
addr
);
logln
(
"\tWriting %2x to %04x
"
,
data
,
addr
);
short
rdev
=
(
short
)(
0x0f
&
dev
);
if
(
dev
==
0x7f
)
{
memory
[
0xffff
&
addr
]
=
data
;
}
if
(
dev
==
0x7f
)
{
synchronized
(
memory
)
{
memory
[
0xffff
&
addr
]
=
data
;
}
}
if
(
dev
<=
0x0f
)
{
short
devOff
=
deviceMaps
[
rdev
].
getOffset
();
short
devAddr
=
(
short
)(
addr
-
devOff
);
...
...
@@ -170,6 +178,7 @@ public class KBoard extends BaseDevice implements IMemory {
if
(
devices
[
port
]
!=
null
)
{
return
;
}
else
if
(
deviceMaps
[
port
]
!=
null
)
{
return
;
}
if
((
port
==
0
)
&&
(
device
.
getClass
().
isAssignableFrom
(
Kcpu
.
class
))
)
{
cpu
=
(
Kcpu
)
device
;
}
devices
[
port
]
=
device
;
deviceMaps
[
port
]
=
new
KMemoryRange
(
offset
,
device
.
length
());
...
...
@@ -234,8 +243,10 @@ public class KBoard extends BaseDevice implements IMemory {
if
(
port
>=
0x20
)
{
return
new
KMemoryRange
((
short
)
0
,
(
short
)
0
);
}
KMemoryRange
kmr
;
if
(
port
<=
0x0f
)
{
kmr
=
deviceMaps
[
port
];
}
else
{
kmr
=
memDevMaps
[(
short
)(
0x0f
&
port
)];
}
if
((
port
<=
0x0f
)
&&
(
deviceMaps
[
port
]
!=
null
))
{
kmr
=
deviceMaps
[
port
];
}
else
if
((
0x10
<=
port
)
&&
(
port
<=
0x2f
)
&&
(
memDevMaps
[
0xf
&
port
]
!=
null
))
{
kmr
=
memDevMaps
[(
short
)(
0x0f
&
port
)];
}
else
{
return
new
KMemoryRange
((
short
)
0
,
(
short
)
0
);
}
return
new
KMemoryRange
(
kmr
.
getOffset
(),
kmr
.
getLength
());
}
public
void
setDeviceRange
(
short
device
,
short
addr
)
{
...
...
@@ -277,8 +288,11 @@ public class KBoard extends BaseDevice implements IMemory {
dumpMemory
(
filename
,
temp
);
}
public
void
dumpMemory
(
String
filename
,
byte
[]
mem
)
{
byte
[]
test
=
new
byte
[
mem
.
length
];
Arrays
.
fill
(
test
,
(
byte
)
0
);
if
(
Arrays
.
equals
(
mem
,
test
))
{
return
;
}
File
f
=
new
File
(
filename
.
concat
(
".mem.txt"
));
try
{
System
.
out
.
println
(
String
.
format
(
"Writing %s"
,
f
.
getCanonicalPath
()
));
}
catch
(
IOException
x
)
{}
try
{
logln
(
"Writing %s"
,
f
.
getCanonicalPath
(
));
}
catch
(
IOException
x
)
{}
try
(
FileWriter
fw
=
new
FileWriter
(
f
))
{
int
max
=
mem
.
length
;
int
a
;
...
...
@@ -322,7 +336,7 @@ public class KBoard extends BaseDevice implements IMemory {
catch
(
IOException
x
)
{}
f
=
new
File
(
filename
.
concat
(
".mem.bin"
));
try
{
System
.
out
.
println
(
String
.
format
(
"Writing %s"
,
f
.
getCanonicalPath
()
));
}
catch
(
IOException
x
)
{}
try
{
logln
(
"Writing %s"
,
f
.
getCanonicalPath
(
));
}
catch
(
IOException
x
)
{}
try
(
FileOutputStream
fos
=
new
FileOutputStream
(
f
))
{
if
(
mem
.
length
<=
4096
)
{
fos
.
write
(
mem
);
...
...
src/main/java/me/felinewith/kcpu/Kasm.java
View file @
adb5452
...
...
@@ -190,7 +190,7 @@ public class Kasm {
// replace assembler keywords with numbers
if
(
temp
.
contains
(
"BASE"
))
{
temp
=
temp
.
replaceAll
(
"BASE"
,
String
.
format
(
"%d"
,
BASEaddr
));
}
if
(
temp
.
contains
(
"MARK"
))
{
temp
=
temp
.
replaceAll
(
"MARK"
,
String
.
format
(
"%d"
,
mark
));
}
if
(
temp
.
contains
(
"MARK"
))
{
temp
=
temp
.
replaceAll
(
"MARK"
,
String
.
format
(
"%d"
,
pc
-
mark
));
}
Pattern
p
=
Pattern
.
compile
(
"([0-9a-f]+),([0-9]+)"
,
Pattern
.
CASE_INSENSITIVE
);
Matcher
m
=
p
.
matcher
(
temp
);
...
...
@@ -299,11 +299,12 @@ public class Kasm {
byte
[]
bytes
=
compileSegment
(
String
.
format
(
"jmpu %d"
,
max
));
output
.
write
(
bytes
,
0
,
bytes
.
length
);
for
(
a
=
0
;
a
<
max
;
a
++)
{
output
.
write
(
fill
);
}
pc
+=
output
.
size
()
;
pc
+=
max
;
return
output
.
toByteArray
();
}
else
{
opcode
=
OpDirector
.
valueOf
(
parts
[
0
]);
try
{
opcode
=
OpDirector
.
valueOf
(
parts
[
0
]);
}
catch
(
IllegalArgumentException
x
)
{
return
new
byte
[
0
];
}
if
(
verbose
)
{
log
(
"[%10s] "
,
opcode
.
name
());
}
writeShort
(
output
,
opcode
.
getOpcode
());
...
...
src/main/java/me/felinewith/kcpu/Kcpu.java
View file @
adb5452
This diff is collapsed.
Click to expand it.
src/main/java/me/felinewith/kcpu/KcpuExceptions.java
0 → 100644
View file @
adb5452
package
me
.
felinewith
.
kcpu
;
import
java.io.PrintStream
;
import
java.lang.Thread.UncaughtExceptionHandler
;
/**
*
* @author jlhawkwell
*/
public
class
KcpuExceptions
implements
UncaughtExceptionHandler
{
Kcpu
c
;
PrintStream
logger
;
public
KcpuExceptions
(
Kcpu
cpu
,
PrintStream
ps
)
{
c
=
cpu
;
logger
=
ps
;
}
@Override
public
void
uncaughtException
(
Thread
t
,
Throwable
e
)
{
logger
.
format
(
"[%34s] Uncaught Exception: %s\n%s"
,
t
.
getName
(),
e
.
getClass
().
getCanonicalName
(),
e
.
getMessage
());
c
.
recvIrq
((
byte
)
0
);
}
}
src/main/java/me/felinewith/kcpu/Kemulator.java
View file @
adb5452
...
...
@@ -2,6 +2,7 @@ package me.felinewith.kcpu;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
me.felinewith.kcpu.hardware.Kmcu
;
import
me.felinewith.kcpu.memory.BootRom
;
import
me.felinewith.kcpu.memory.Buffer
;
import
org.apache.commons.cli.CommandLine
;
...
...
@@ -18,9 +19,6 @@ import org.apache.commons.cli.ParseException;
*/
public
class
Kemulator
{
public
static
void
main
(
String
[]
args
)
{
KBoard
kb
=
new
KBoard
();
Buffer
bb
=
new
Buffer
();
if
(
args
.
length
!=
0
)
{
for
(
String
s
:
args
)
{
if
(
s
.
equals
(
"-kasm"
))
{
Kasm
.
main
(
args
);
return
;
}
...
...
@@ -30,6 +28,7 @@ public class Kemulator {
ArrayList
<
Option
>
option
=
new
ArrayList
<>();
option
.
add
(
Option
.
builder
(
"b"
)
.
longOpt
(
"bootrom"
)
.
desc
(
"Loads a given set of ROMs into the BootRom"
)
.
argName
(
"bootrom"
)
.
hasArg
()
.
numberOfArgs
(
8
)
...
...
@@ -37,6 +36,12 @@ public class Kemulator {
);
option
.
add
(
Option
.
builder
(
"h"
)
.
longOpt
(
"help"
)
.
desc
(
"Displays this help"
)
.
build
()
);
option
.
add
(
Option
.
builder
(
"v"
)
.
longOpt
(
"verbose"
)
.
desc
(
"Enables verbose output (useful for debugging)"
)
.
build
()
);
...
...
@@ -55,6 +60,7 @@ public class Kemulator {
}
BootRom
bootrom
=
new
BootRom
();
boolean
verbose
=
false
;
if
(
line
!=
null
)
{
if
(
line
.
hasOption
(
"h"
))
{
...
...
@@ -69,15 +75,34 @@ public class Kemulator {
catch
(
IOException
x
)
{}
}
}
if
(
line
.
hasOption
(
"v"
))
{
verbose
=
true
;
}
}
KBoard
kb
=
new
KBoard
();
Kcpu
cpu
=
new
Kcpu
(
kb
);
Kmcu
mcu
=
new
Kmcu
();
Buffer
bb
=
new
Buffer
();
bb
.
setInputStream
(
System
.
in
);
bb
.
setOutputStream
(
System
.
out
);
if
(
verbose
)
{
cpu
.
setLogger
(
System
.
err
);
mcu
.
setLogger
(
System
.
err
);
bb
.
setLogger
(
System
.
err
);
}
kb
.
attachDevice
(
0x8000
,
cpu
);
kb
.
attachDevice
(
0x8800
,
mcu
);
kb
.
attachMemory
(
0xff00
,
bb
);
kb
.
attachMemory
(
0x1000
,
bootrom
);
kb
.
init
();
if
(
verbose
)
{
kb
.
init
(
System
.
err
);
System
.
err
.
flush
();
}
else
{
kb
.
init
();
}
System
.
out
.
flush
();
}
...
...
src/main/java/me/felinewith/kcpu/hardware/Kmcu.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
hardware
;
import
java.io.PrintStream
;
import
java.util.Arrays
;
import
me.felinewith.kcpu.hardware.kmcu.KmcuOp
;
import
me.felinewith.kcpu.util.BaseDevice
;
...
...
@@ -11,66 +10,47 @@ import me.felinewith.kcpu.util.Converter;
* @author jlhawkwell
*/
public
class
Kmcu
extends
BaseDevice
{
private
static
PrintStream
outer
;
/**
* @return the outer
*/
public
static
PrintStream
getOuter
()
{
return
outer
;
}
/**
* @param aOuter the outer to set
*/
public
static
void
setOuter
(
PrintStream
aOuter
)
{
outer
=
aOuter
;
}
private
static
void
log
(
String
format
,
Object
...
vals
)
{
if
(
outer
==
null
)
{
return
;
}
outer
.
print
(
String
.
format
(
format
,
vals
));
}
private
static
void
logln
(
String
format
,
Object
...
vals
)
{
if
(
outer
==
null
)
{
return
;
}
outer
.
println
(
String
.
format
(
format
,
vals
));
}
public
Kmcu
()
{
setOuter
(
System
.
err
);
memory
=
new
byte
[
0x20
];
name
=
"Kmcp"
;
}
private
void
workInit
(
short
setting
)
{
byte
[]
reg
;
if
(
setting
==
0
)
{
reg
=
Arrays
.
copyOfRange
(
memory
,
0
,
7
);
}
else
{
reg
=
Arrays
.
copyOfRange
(
memory
,
8
,
15
);
}
short
starts
;
switch
(
setting
)
{
case
0
:
starts
=
0x10
;
break
;
case
1
:
starts
=
0x12
;
break
;
default
:
starts
=
0
;
break
;
}
byte
[]
data
=
{
read
(
starts
),
read
(
starts
+
1
)
};
short
opcode
=
Converter
.
bytes2short
(
data
);
KmcuOp
od
=
new
KmcuOp
(
opcode
);
logln
(
"Kmcp : [%10s] %04x -> %04x %04x %04x %04x %04x %04x %04x %04x"
,
((
od
.
name
()
==
null
)?
"nop"
:
od
.
name
()),
opcode
,
reg
[
0
],
reg
[
1
],
reg
[
2
],
reg
[
3
],
reg
[
4
],
reg
[
5
],
reg
[
6
],
reg
[
7
]
);
reg
=
performCalc
(
od
,
reg
);
int
a
;
int
c
;
if
(
setting
==
0
)
{
a
=
0
;
}
else
{
a
=
8
;
}
for
(
c
=
0
;
c
<
8
;
c
++)
{
memory
[
a
+
c
]
=
reg
[
c
];
synchronized
(
memory
)
{
byte
[]
reg
;
if
(
setting
==
0
)
{
reg
=
Arrays
.
copyOfRange
(
memory
,
0
,
7
);
}
else
{
reg
=
Arrays
.
copyOfRange
(
memory
,
8
,
15
);
}
short
starts
;
switch
(
setting
)
{
case
0
:
starts
=
0x10
;
break
;
case
1
:
starts
=
0x12
;
break
;
default
:
starts
=
0
;
break
;
}
byte
[]
data
=
{
read
(
starts
),
read
(
starts
+
1
)
};
short
opcode
=
Converter
.
bytes2short
(
data
);
KmcuOp
od
=
new
KmcuOp
(
opcode
);
logln
(
"Kmcp : [%10s] %04x -> %04x %04x %04x %04x %04x %04x %04x %04x"
,
((
od
.
name
()
==
null
)?
"nop"
:
od
.
name
()),
opcode
,
reg
[
0
],
reg
[
1
],
reg
[
2
],
reg
[
3
],
reg
[
4
],
reg
[
5
],
reg
[
6
],
reg
[
7
]
);
reg
=
performCalc
(
od
,
reg
);
int
a
;
int
c
;
if
(
setting
==
0
)
{
a
=
0
;
}
else
{
a
=
8
;
}
for
(
c
=
0
;
c
<
8
;
c
++)
{
memory
[
a
+
c
]
=
reg
[
c
];
}
}
}
...
...
@@ -102,6 +82,7 @@ public class Kmcu extends BaseDevice {
case
COS:
out
[
0
]
=
Converter
.
double2byte
(
Math
.
cos
(
Converter
.
byte2double
(
work
[
0
])));
break
;
case
COSH:
out
[
0
]
=
Converter
.
double2byte
(
Math
.
cosh
(
Converter
.
byte2double
(
work
[
0
])));
break
;
case
DIV:
if
(
work
[
1
]
==
0
)
{
break
;
}
out
[
0
]
=
Converter
.
float2byte
(
work
[
0
]
/
work
[
1
]);
out
[
4
]
=
Converter
.
int2byte
(
work
[
0
]
%
work
[
1
]);
break
;
...
...
@@ -185,6 +166,7 @@ public class Kmcu extends BaseDevice {
case
COS:
out
[
0
]
=
Converter
.
double2short
(
Math
.
cos
(
Converter
.
short2double
(
work
[
0
])));
break
;
case
COSH:
out
[
0
]
=
Converter
.
double2short
(
Math
.
cosh
(
Converter
.
short2double
(
work
[
0
])));
break
;
case
DIV:
if
(
work
[
1
]
==
0
)
{
break
;
}
out
[
0
]
=
Converter
.
float2short
(
work
[
0
]
/
work
[
1
]);
out
[
1
]
=
Converter
.
int2short
(
work
[
0
]
%
work
[
1
]);
break
;
...
...
@@ -281,6 +263,7 @@ public class Kmcu extends BaseDevice {
case
COS:
out
[
0
]
=
Converter
.
double2int
(
Math
.
cos
(
Converter
.
int2double
(
work
[
0
])));
break
;
case
COSH:
out
[
0
]
=
Converter
.
double2int
(
Math
.
cosh
(
Converter
.
int2double
(
work
[
0
])));
break
;
case
DIV:
if
(
work
[
1
]
==
0
)
{
break
;
}
out
[
0
]
=
Converter
.
float2int
(
work
[
0
]
/
work
[
1
]);
out
[
1
]
=
work
[
0
]
%
work
[
1
];
break
;
...
...
@@ -381,6 +364,7 @@ public class Kmcu extends BaseDevice {
case
COS:
out
[
0
]
=
Converter
.
double2float
(
Math
.
cos
(
Converter
.
float2double
(
work
[
0
])));
break
;
case
COSH:
out
[
0
]
=
Converter
.
double2float
(
Math
.
cosh
(
Converter
.
float2double
(
work
[
0
])));
break
;
case
DIV:
if
(
work
[
1
]
==
0
)
{
break
;
}
out
[
0
]
=
work
[
0
]
/
work
[
1
];
out
[
1
]
=
work
[
0
]
%
work
[
1
];
break
;
...
...
@@ -460,7 +444,7 @@ public class Kmcu extends BaseDevice {
return
output
;
}
@Override
public
void
m
emIrq
(
short
addr
,
byte
irq
)
{
@Override
public
void
recvM
emIrq
(
short
addr
,
byte
irq
)
{
if
(
0
<=
addr
&&
addr
<=
memory
.
length
)
{
workInit
((
short
)
0
);
workInit
((
short
)
1
);
...
...
src/main/java/me/felinewith/kcpu/interfaces/IDevice.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
interfaces
;
import
java.io.PrintStream
;
import
java.util.concurrent.Future
;
import
me.felinewith.kcpu.util.HardwareFinished
;
/**
*
* @author jlhawkwell
*/
public
interface
IDevice
extends
IMemory
{
public
void
init
(
IMemory
board
);
public
void
init
(
PrintStream
logger
,
IMemory
board
);
public
abstract
void
sendIrq
(
byte
irq
);
public
abstract
void
recvIrq
(
byte
irq
);
public
Future
<
HardwareFinished
>
sendIrq
(
byte
irq
);
public
void
recvIrq
(
byte
irq
);
}
src/main/java/me/felinewith/kcpu/interfaces/IMemory.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
interfaces
;
import
java.io.PrintStream
;
import
java.util.concurrent.Future
;
import
me.felinewith.kcpu.util.HardwareFinished
;
/**
*
* @author jlhawkwell
*/
public
interface
IMemory
{
public
abstract
short
length
();
public
abstract
byte
read
(
short
addr
);
public
abstract
void
write
(
short
addr
,
byte
data
);
public
abstract
void
memIrq
(
short
addr
,
byte
irq
);
public
void
init
();
public
void
init
(
PrintStream
logger
);
public
short
length
();
public
byte
read
(
short
addr
);
public
void
write
(
short
addr
,
byte
data
);
public
Future
<
HardwareFinished
>
sendMemIrq
(
short
addr
,
byte
irq
);
public
void
recvMemIrq
(
short
addr
,
byte
irq
);
public
void
setLogger
(
PrintStream
logger
);
public
void
powerOff
();
}
src/main/java/me/felinewith/kcpu/memory/BootRom.java
View file @
adb5452
...
...
@@ -31,36 +31,68 @@ public class BootRom extends BaseMemory {
// hardcoding some bootrom
//writeBytes(kasm.compileSegment("movs $0 r2"));
kasm
.
compileSegment
(
"mark"
);
writeBytes
(
kasm
.
compileSegment
(
"add r0
16
"
));
writeBytes
(
kasm
.
compileSegment
(
"add r0
8
"
));
writeBytes
(
kasm
.
compileSegment
(
"add r2 1"
));
writeBytes
(
kasm
.
compileSegment
(
"movs $0 r2"
));
writeBytes
(
kasm
.
compileSegment
(
"jdl
r0 512
mark"
));
writeBytes
(
kasm
.
compileSegment
(
"jdl
e r2 30
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
.
compileSegment
(
"mov r2 2"
));
writeBytes
(
kasm
.
compileSegment
(
"mov r3 0"
));
kasm
.
compileSegment
(
"mark"
);
writeBytes
(
kasm
.
compileSegment
(
"devp r3"
));
writeBytes
(
kasm
.
compileSegment
(
"movs ar.2 r0"
));
writeBytes
(
kasm
.
compileSegment
(
"add r2 8"
));
writeBytes
(
kasm
.
compileSegment
(
"add r3 1"
));
writeBytes
(
kasm
.
compileSegment
(
"jdle r3 32 mark"
));
writeBytes
(
kasm
.
compileSegment
(
"mov r2 4"
));
writeBytes
(
kasm
.
compileSegment
(
"mov r3 0"
));
kasm
.
compileSegment
(
"mark"
);
writeBytes
(
kasm
.
compileSegment
(
"devp r3"
));
writeBytes
(
kasm
.
compileSegment
(
"movs ar.2 r1"
));
writeBytes
(
kasm
.
compileSegment
(
"add r2 8"
));
writeBytes
(
kasm
.
compileSegment
(
"add r3 1"
));
writeBytes
(
kasm
.
compileSegment
(
"jdle r3 32 mark"
));
writeBytes
(
kasm
.
compileSegment
(
"gpc"
));
writeBytes
(
kasm
.
compileSegment
(
"mov ff00,16 61,16"
));
writeBytes
(
kasm
.
compileSegment
(
"irqm ff01,16"
));
writeBytes
(
kasm
.
compileSegment
(
"movs r0 1f00,16"
));
writeBytes
(
kasm
.
compileSegment
(
"mov r1 0"
));
kasm
.
compileSegment
(
"mark"
);
writeBytes
(
kasm
.
compileSegment
(
"mov ar.0 ar.1"
));
writeBytes
(
kasm
.
compileSegment
(
"add r1 1"
));
writeBytes
(
kasm
.
compileSegment
(
"add r0 1"
));
writeBytes
(
kasm
.
compileSegment
(
"jdle r1 ff,16 mark"
));
writeBytes
(
kasm
.
compileSegment
(
"irqm 1f00,16"
));
/*writeBytes(kasm.compileSegment("gpc"));
writeBytes(kasm.compileSegment("movs r0 60,16"));
kasm.compileSegment("mark");
writeBytes(kasm.compileSegment("add r0 1"));
writeBytes(kasm.compileSegment("mov ff00,16 r0"));
writeBytes(kasm.compileSegment("irqmh ff01,16"));
writeBytes(kasm.compileSegment("jdl r0 7a,16 mark")); // */
}
// 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
recvMemIrq
(
short
addr
,
byte
irq
)
{
writable
=
false
;
logln
(
"BootRom locked read-only"
);
}
@Override
public
void
write
(
short
addr
,
byte
data
)
{
if
(!
writable
)
{
return
;
}
super
.
write
(
addr
,
data
);
}
private
void
writeByte
(
byte
input
)
{
memory
[
writepos
]
=
input
;
writepos
++;
if
(
writepos
==
memory
.
length
)
{
writepos
=
0
;
}
synchronized
(
memory
)
{
memory
[
writepos
]
=
input
;
writepos
++;
if
(
writepos
==
memory
.
length
)
{
writepos
=
0
;
}
}
}
private
void
writeBytes
(
byte
[]
input
)
{
...
...
src/main/java/me/felinewith/kcpu/memory/Buffer.java
View file @
adb5452
...
...
@@ -40,46 +40,50 @@ public class Buffer extends BaseMemory {
bufout
=
new
OutputStreamWriter
(
stdout
);
}
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
short
a
;
short
value
;
if
(
addr
<=
0x0f
)
{
try
{
for
(
a
=
0
;
a
<=
0x0f
;
a
++)
{
if
(
memory
[
a
]
==
0
)
{
break
;
}
bufout
.
write
(
memory
[
a
]);
memory
[
a
]
=
0
;
@Override
public
void
recvMemIrq
(
short
addr
,
byte
irq
)
{
synchronized
(
memory
)
{
short
a
;
short
value
;
if
(
addr
<=
0x0f
)
{
try
{
for
(
a
=
0
;
a
<=
0x0f
;
a
++)
{
if
(
memory
[
a
]
==
0
)
{
break
;
}
bufout
.
write
(
memory
[
a
]);
memory
[
a
]
=
0
;
}
bufout
.
flush
();
}
bufout
.
flush
();
catch
(
IOException
x
)
{}
}
catch
(
IOException
x
)
{}
}
if
(
addr
>=
0x10
)
{
try
{
if
(
bufin
.
ready
()
)
{
byte
[]
temp
=
bufin
.
toString
().
getBytes
(
cs
);
int
len
=
temp
.
length
;
if
(
len
>=
16
)
{
len
=
16
;
}
for
(
a
=
0
;
a
<
len
;
a
++)
{
value
=
(
short
)(
0x10
+
a
);
memory
[
value
]
=
temp
[
a
];
if
(
addr
>=
0x10
)
{
try
{
if
(
bufin
.
ready
()
)
{
byte
[]
temp
=
bufin
.
toString
().
getBytes
(
cs
);
int
len
=
temp
.
length
;
if
(
len
>=
16
)
{
len
=
16
;
}
for
(
a
=
0
;
a
<
len
;
a
++)
{
value
=
(
short
)(
0x10
+
a
);
memory
[
value
]
=
temp
[
a
];
}
}
}
catch
(
IOException
e
)
{}
}
catch
(
IOException
e
)
{}
}
}
@Override
public
byte
read
(
short
addr
)
{
if
(
addr
>=
memory
.
length
)
{
return
(
byte
)
0xff
;
}
// input buffer clears when read
if
(
addr
>=
0x10
)
{
byte
b
=
memory
[
addr
];
memory
[
addr
]
=
0
;
return
b
;
synchronized
(
memory
)
{
if
(
addr
>=
memory
.
length
)
{
return
(
byte
)
0xff
;
}
// input buffer clears when read
if
(
addr
>=
0x10
)
{
byte
b
=
memory
[
addr
];
memory
[
addr
]
=
0
;
return
b
;
}
return
memory
[
addr
];
}
return
memory
[
addr
];
}
@Override
public
void
write
(
short
addr
,
byte
data
)
{
...
...
src/main/java/me/felinewith/kcpu/opcodes/BasicMath.java
View file @
adb5452
...
...
@@ -18,6 +18,7 @@ public class BasicMath implements IOpcodeHandler {
switch
(
opcode
)
{
case
ADD:
out
=
ValueHelper
.
writeShort
(
0
,
ref
,
out
,
values
,
memory
,
new
Integer
(
va
+
vb
).
shortValue
());
break
;
case
DIV:
if
(
vb
==
0
)
{
return
out
;
}
out
=
ValueHelper
.
writeShort
(
0
,
ref
,
out
,
values
,
memory
,
new
Integer
(
va
/
vb
).
shortValue
());
out
=
ValueHelper
.
writeShort
(
1
,
ref
,
out
,
values
,
memory
,
new
Integer
(
va
%
vb
).
shortValue
());
break
;
...
...
src/main/java/me/felinewith/kcpu/opcodes/OpDirector.java
View file @
adb5452
...
...
@@ -32,11 +32,13 @@ public enum OpDirector {
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
(
0x
10
03
,
"port: get device address for device on port"
),
// get device address from port
DEVP
(
0x
ff
03
,
"port: get device address for device on port"
),
// get device address from port
// interrupts
IRQD
(
0xff10
,
"port: send interrupt to port"
),
// interrupt to port
IRQM
(
0xff11
,
"addr: send interrupt to memory address"
),
// interrupt to memory
IRQDH
(
0xff12
,
"port: send interrupt to port and halt"
),
IRQMH
(
0xff13
,
"addr: send interrupt to memory address and halt"
),
// jumps
JMP
(
0xff18
,
"Alias of JMPU"
),
// jump up
...
...
src/main/java/me/felinewith/kcpu/util/BaseDevice.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
util
;
import
java.io.PrintStream
;
import
java.util.concurrent.Future
;
import
me.felinewith.kcpu.interfaces.IDevice
;
import
me.felinewith.kcpu.interfaces.IMemory
;
...
...
@@ -14,14 +16,19 @@ public abstract class BaseDevice extends BaseMemory implements IDevice {
@Override
public
void
init
(
IMemory
system
)
{
board
=
system
;
init
();
}
@Override
public
void
init
(
PrintStream
ps
,
IMemory
system
)
{
super
.
init
(
ps
);
init
(
system
);
}
protected
void
sendIrq
()
{
protected
Future
<
HardwareFinished
>
sendIrq
()
{
int
addr
=
memory
.
length
-
1
;
s
endIrq
(
memory
[
addr
]);
s
ynchronized
(
memory
)
{
return
sendIrq
(
memory
[
addr
]);
}
}
@Override
public
void
sendIrq
(
byte
irq
)
{
}
@Override
public
Future
<
HardwareFinished
>
sendIrq
(
byte
irq
)
{
return
new
FakeFuture
();
}
@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 @
adb5452
package
me
.
felinewith
.
kcpu
.
util
;
import
java.io.PrintStream
;
import
java.util.concurrent.Future
;
import
me.felinewith.kcpu.interfaces.IMemory
;
/**
...
...
@@ -9,24 +11,46 @@ import me.felinewith.kcpu.interfaces.IMemory;
public
abstract
class
BaseMemory
implements
IMemory
{
protected
byte
[]
memory
;
protected
PrintStream
logger
=
null
;
protected
boolean
lastLineWasNewLine
=
false
;
@Override
public
short
length
()
{
return
(
short
)
memory
.
length
;
@Override
public
void
init
()
{}
@Override
public
void
init
(
PrintStream
ps
)
{
logger
=
ps
;
init
();
}
@Override
public
short
length
()
{
return
(
short
)
memory
.
length
;
}
public
final
byte
read
(
int
addr
)
{
return
read
((
short
)
addr
);
}
@Override
public
byte
read
(
short
addr
)
{
if
(
(
0xffff
&
addr
)
>
length
()
)
{
return
(
byte
)
0xff
;
}
return
memory
[
0xffff
&
addr
];
synchronized
(
memory
)
{
return
memory
[
0xffff
&
addr
];
}
}
public
final
void
write
(
int
addr
,
byte
data
)
{
write
((
short
)
addr
,
data
);
}
@Override
public
void
write
(
short
addr
,
byte
data
)
{
if
(
(
0xffff
&
addr
)
>
length
()
)
{
return
;
}
memory
[
0xffff
&
addr
]
=
data
;
synchronized
(
memory
)
{
memory
[
0xffff
&
addr
]
=
data
;
}
}
@Override
public
void
memIrq
(
short
addr
,
byte
irq
)
{
}
@Override
public
Future
<
HardwareFinished
>
sendMemIrq
(
short
addr
,
byte
irq
)
{
return
new
FakeFuture
();
}
@Override
public
void
recvMemIrq
(
short
addr
,
byte
irq
)
{}
@Override
public
void
setLogger
(
PrintStream
ps
)
{
logger
=
ps
;
}
@Override
public
void
powerOff
()
{
}
protected
void
log
(
String
format
,
Object
...
args
)
{
if
(
logger
==
null
)
{
return
;
}
if
(
lastLineWasNewLine
)
{
logger
.
format
(
"[%-34s] "
,
Thread
.
currentThread
().
getName
());
lastLineWasNewLine
=
false
;
}
logger
.
format
(
format
,
args
);
}
protected
void
logln
(
String
format
,
Object
...
args
)
{
if
(
logger
==
null
)
{
return
;
}
log
(
format
,
args
);
logger
.
println
();
lastLineWasNewLine
=
true
;
}
}
src/main/java/me/felinewith/kcpu/util/FakeFuture.java
0 → 100644
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
util
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
/**
*
* @author jlhawkwell
*/
public
class
FakeFuture
implements
Future
<
HardwareFinished
>
{
@Override
public
boolean
cancel
(
boolean
mayInterruptIfRunning
)
{
return
false
;
}
@Override
public
boolean
isCancelled
()
{
return
true
;
}
@Override
public
boolean
isDone
()
{
return
true
;
}
@Override
public
HardwareFinished
get
()
throws
InterruptedException
,
ExecutionException
{
return
new
HardwareFinished
();
}
@Override
public
HardwareFinished
get
(
long
timeout
,
TimeUnit
unit
)
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
return
new
HardwareFinished
();
}
}
src/main/java/me/felinewith/kcpu/util/HardwareFinished.java
0 → 100644
View file @
adb5452
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
me
.
felinewith
.
kcpu
.
util
;
/**
*
* @author jlhawkwell
*/
public
class
HardwareFinished
{
}
src/main/java/me/felinewith/kcpu/util/HardwareMemIrq.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
util
;
import
java.util.
TimerTask
;
import
java.util.
concurrent.Callable
;
import
me.felinewith.kcpu.interfaces.IMemory
;
/**
*
* @author jlhawkwell
*/
public
class
HardwareMemIrq
extends
TimerTask
{
public
class
HardwareMemIrq
implements
Callable
<
HardwareFinished
>
{
IMemory
id
;
short
a
;
...
...
@@ -18,8 +18,10 @@ public class HardwareMemIrq extends TimerTask {
a
=
addr
;
i
=
irq
;
}
@Override
public
void
run
()
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"memIRQ-%02x_%04x-%x"
,
i
,
a
,
Thread
.
currentThread
().
getId
()
));
id
.
memIrq
(
a
,
i
);
@Override
public
HardwareFinished
call
()
throws
Exception
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"memIRQ-%02x_%04x-%016x"
,
i
,
a
,
Thread
.
currentThread
().
getId
()
));
id
.
recvMemIrq
(
a
,
i
);
return
new
HardwareFinished
();
}
}
src/main/java/me/felinewith/kcpu/util/HardwareRecvIrq.java
View file @
adb5452
package
me
.
felinewith
.
kcpu
.
util
;
import
java.util.
TimerTask
;
import
java.util.
concurrent.Callable
;
import
me.felinewith.kcpu.interfaces.IDevice
;
/**
*
* @author jlhawkwell
*/
public
class
HardwareRecvIrq
extends
TimerTask
{
public
class
HardwareRecvIrq
implements
Callable
<
HardwareFinished
>
{
IDevice
id
;
byte
i
;
...
...
@@ -16,8 +16,10 @@ public class HardwareRecvIrq extends TimerTask {
id
=
device
;
i
=
irq
;
}
@Override
public
void
run
()
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"recvIRQ-%02x-%x"
,
i
,
Thread
.
currentThread
().
getId
()
));
@Override
public
HardwareFinished
call
()
throws
Exception
{
Thread
.
currentThread
().
setName
(
String
.
format
(
"recvIRQ-%02x-%016x"
,
i
,
Thread
.
currentThread
().
getId
()
));
id
.
recvIrq
(
i
);
return
new
HardwareFinished
();
}
}
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