Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
S
SWEN90006-A1-2018
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Linyuan Zhao
SWEN90006-A1-2018
Commits
ed3d0c24
Commit
ed3d0c24
authored
6 years ago
by
Linyuan Zhao
Browse files
Options
Downloads
Patches
Plain Diff
Upload New File
parent
bdc3670a
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
mutants/mutant-4/swen90006/machine/Machine.java
+303
-0
303 additions, 0 deletions
mutants/mutant-4/swen90006/machine/Machine.java
with
303 additions
and
0 deletions
mutants/mutant-4/swen90006/machine/Machine.java
0 → 100644
+
303
−
0
View file @
ed3d0c24
package
swen90006.machine
;
import
java.util.Arrays
;
import
java.util.List
;
public
class
Machine
{
/** arithmetic instructions each take three registers as arguments with the
* destination register appearing first
*/
/** add rd rs1 rs2 =~ rd = rs1 + rs2 */
public
static
final
String
INSTRUCTION_ADD
=
"add"
;
/** sub rd rs1 rs2 =~ rd = rs1 - rs2 */
public
static
final
String
INSTRUCTION_SUBTRACT
=
"sub"
;
/** mul rd rs1 rs2 =~ rd = rs1 * rs2 */
public
static
final
String
INSTRUCTION_MULT
=
"mul"
;
/** div rd rs1 rs2 =~ rd = rs1 / rs2 */
public
static
final
String
INSTRUCTION_DIVIDE
=
"div"
;
/** ret rs =~ return rs */
public
static
final
String
INSTRUCTION_RETURN
=
"ret"
;
/** ldr rd rs offs =~ rd = rs[offs] */
public
static
final
String
INSTRUCTION_LOAD
=
"ldr"
;
/** str ra offs rb =~ ra[offs] = rb */
public
static
final
String
INSTRUCTION_STORE
=
"str"
;
/** mov rd val =~ rd = val */
public
static
final
String
INSTRUCTION_MOVE
=
"mov"
;
/** jmp offs =~ pc = pc + offs */
public
static
final
String
INSTRUCTION_JUMP
=
"jmp"
;
/** jz ra offs =~ if (ra == 0) pc = pc + offs else pc = pc + 1 */
public
static
final
String
INSTRUCTION_JZ
=
"jz"
;
public
static
final
int
NUM_REGS
=
32
;
public
static
final
int
MAX_REG
=
(
NUM_REGS
-
1
);
public
static
final
int
MEMORY_SIZE
=
65536
;
/* 4 x as much memory as a 64 */
public
static
final
int
MAX_ADDR
=
MEMORY_SIZE
-
1
;
private
int
[]
memory
;
private
int
[]
regs
;
private
int
count
=
0
;
/* counts number of instructions executed so far */
public
Machine
()
{
memory
=
new
int
[
MEMORY_SIZE
];
regs
=
new
int
[
NUM_REGS
];
count
=
0
;
}
private
void
do_add
(
int
dest
,
int
src1
,
int
src2
)
{
regs
[
dest
]
=
regs
[
src1
]
+
regs
[
src2
];
}
private
void
do_sub
(
int
dest
,
int
src1
,
int
src2
)
{
regs
[
dest
]
=
regs
[
src1
]
-
regs
[
src2
];
}
private
void
do_mult
(
int
dest
,
int
src1
,
int
src2
)
{
regs
[
dest
]
=
regs
[
src1
]
*
regs
[
src2
];
}
private
void
do_div
(
int
dest
,
int
src1
,
int
src2
)
{
if
(
regs
[
src2
]
==
0
){
/* no op */
}
else
{
regs
[
dest
]
=
regs
[
src1
]
/
regs
[
src2
];
}
}
private
void
do_load
(
int
dest
,
int
src
,
int
offs
)
{
if
(
regs
[
src
]
+
offs
>
MAX_ADDR
){
/* no op */
}
else
if
(
regs
[
src
]
+
offs
<
0
){
/* no op */
}
else
{
regs
[
dest
]
=
memory
[
regs
[
src
]
+
offs
];
}
}
private
void
do_store
(
int
a
,
int
offs
,
int
b
)
{
if
(
regs
[
a
]
+
offs
>
MAX_ADDR
){
/* no op */
}
else
if
(
regs
[
a
]
+
offs
<
0
){
/* no op */
}
else
{
memory
[
regs
[
a
]
+
offs
]
=
regs
[
b
];
}
}
private
void
do_move
(
int
rd
,
int
val
){
regs
[
rd
]
=
val
;
}
private
int
parseReg
(
String
s
)
throws
InvalidInstructionException
{
if
(
s
.
length
()
<
2
){
throw
new
InvalidInstructionException
();
}
if
(
s
.
charAt
(
0
)
!=
'r'
){
throw
new
InvalidInstructionException
();
}
String
numstr
=
s
.
substring
(
1
);
int
num
=
0
;
try
{
num
=
Integer
.
parseInt
(
numstr
);
}
catch
(
Exception
e
){
throw
new
InvalidInstructionException
();
}
validate_reg
(
num
);
return
num
;
}
private
int
parseOffset
(
String
s
)
throws
InvalidInstructionException
{
int
num
=
0
;
try
{
num
=
Integer
.
parseInt
(
s
);
}
catch
(
Exception
e
){
throw
new
InvalidInstructionException
();
}
validate_offset
(
num
);
return
num
;
}
private
void
validate_reg
(
int
reg
)
throws
InvalidInstructionException
{
if
(
reg
<
0
||
reg
>
MAX_REG
)
{
throw
new
InvalidInstructionException
();
}
}
private
void
validate_offset
(
int
offset
)
throws
InvalidInstructionException
{
if
(
offset
<
-
MAX_ADDR
||
offset
>
MAX_ADDR
)
{
throw
new
InvalidInstructionException
();
}
}
/** Execute an assembly program.
*
* @param prog is the program to execute as an iterable collection of strings,
* each of which is a single instruction.
* @return the program's return value.
* @throws Exception when program has unrecognised or
* invalid instructions, or when it returns no result when it finishes
*/
int
execute
(
List
<
String
>
instructions
)
throws
InvalidInstructionException
,
NoReturnValueException
{
int
instructionsExecuted
=
0
;
int
pc
=
0
;
final
int
progLength
=
instructions
.
size
();
while
(
true
){
if
(
pc
<
0
||
pc
>=
progLength
){
/* will cause NoReturnValueException to be thrown
* but that is not a bug and and indeed is what the
* VM is supposed to do if the pc becomes negative,
* since in this case the program's execution
* finishes early without a return value having
* been produced. */
break
;
}
String
inst
=
instructions
.
get
(
pc
);
/* strip leading and trailing whitespace */
inst
=
inst
.
toLowerCase
().
replaceAll
(
"^\\s+"
,
""
).
replaceAll
(
"\\s+$"
,
""
);
/* strip out any comments */
String
[]
toks
=
inst
.
split
(
";"
);
inst
=
toks
[
0
];
/* check for blank lines */
if
(
inst
.
equals
(
""
)){
pc
=
pc
+
1
;
count
++;
continue
;
}
instructionsExecuted
++;
/* now tokenize by splitting on whitespace */
toks
=
inst
.
split
(
"\\s+"
);
/* check minimum number of tokens */
if
(
toks
.
length
<
2
){
throw
new
InvalidInstructionException
();
}
if
(
toks
[
0
].
equals
(
INSTRUCTION_ADD
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
rs1
=
parseReg
(
toks
[
2
]);
int
rs2
=
parseReg
(
toks
[
3
]);
do_add
(
rd
,
rs1
,
rs2
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_SUBTRACT
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
rs1
=
parseReg
(
toks
[
2
]);
int
rs2
=
parseReg
(
toks
[
3
]);
do_sub
(
rd
,
rs1
,
rs2
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_MULT
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
rs1
=
parseReg
(
toks
[
2
]);
int
rs2
=
parseReg
(
toks
[
3
]);
do_mult
(
rd
,
rs1
,
rs2
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_DIVIDE
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
rs1
=
parseReg
(
toks
[
2
]);
int
rs2
=
parseReg
(
toks
[
3
]);
do_div
(
rd
,
rs1
,
rs2
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_RETURN
)){
int
rs
=
parseReg
(
toks
[
1
]);
count
++;
return
regs
[
rs
];
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_LOAD
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
rs
=
parseReg
(
toks
[
2
]);
int
offs
=
parseOffset
(
toks
[
3
]);
do_load
(
rd
,
rs
,
offs
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_STORE
)){
if
(
toks
.
length
!=
4
){
throw
new
InvalidInstructionException
();
}
int
ra
=
parseReg
(
toks
[
1
]);
int
offs
=
parseOffset
(
toks
[
2
]);
int
rb
=
parseReg
(
toks
[
3
]);
do_store
(
ra
,
offs
,
rb
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_MOVE
)){
if
(
toks
.
length
!=
3
){
throw
new
InvalidInstructionException
();
}
int
rd
=
parseReg
(
toks
[
1
]);
int
offs
=
parseOffset
(
toks
[
2
]);
do_move
(
rd
,
offs
);
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_JUMP
)){
if
(
toks
.
length
!=
2
){
throw
new
InvalidInstructionException
();
}
int
offs
=
parseOffset
(
toks
[
1
]);
pc
=
pc
+
offs
;
count
++;
continue
;
/* avoid default increment of pc below */
}
else
if
(
toks
[
0
].
equals
(
INSTRUCTION_JZ
)){
if
(
toks
.
length
!=
3
){
throw
new
InvalidInstructionException
();
}
int
ra
=
parseReg
(
toks
[
1
]);
int
offs
=
parseOffset
(
toks
[
2
]);
if
(
regs
[
ra
]
==
0
){
pc
=
pc
+
offs
;
}
else
{
pc
=
pc
+
1
;
}
count
++;
continue
;
/* avoid default increment the pc below */
}
else
{
System
.
err
.
println
(
"Unrecognised instruction: "
+
inst
);
throw
new
InvalidInstructionException
();
}
count
++;
pc
=
pc
+
1
;
}
/* got here without returning already... */
throw
new
NoReturnValueException
();
}
/**
* get the number of instructions successfully executed by the VM so far
*/
public
int
getCount
(){
return
count
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment