Skip to content

Commit

Permalink
Add support for register dereferencing in the first operand of the mo…
Browse files Browse the repository at this point in the history
…ve instruction.
  • Loading branch information
aleury committed Jan 21, 2024
1 parent 1285d6b commit 5262115
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 31 deletions.
3 changes: 2 additions & 1 deletion ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func (os InstructionStatement) statementNode() {}
func (os InstructionStatement) TokenLiteral() string { return os.Token.Literal }

type RegisterLiteral struct {
Token token.Token // the token.REGISTER token
Token token.Token // the token.REGISTER token
Dereferenced bool
}

func (rl RegisterLiteral) expressionNode() {}
Expand Down
58 changes: 34 additions & 24 deletions gmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
OpADDA
OpMULA
OpMVAX
OpMVIAX
OpMVAY
OpMVAV
OpMVVA
Expand Down Expand Up @@ -68,28 +69,29 @@ var registers = map[string]Word{
}

var opcodes = map[string]Word{
"HALT": OpHALT,
"NOOP": OpNOOP,
"OUTA": OpOUTA,
"INCA": OpINCA,
"INCX": OpINCX,
"INCY": OpINCY,
"DECA": OpDECA,
"DECX": OpDECX,
"DECY": OpDECY,
"ADDA": OpADDA,
"MULA": OpMULA,
"MVAX": OpMVAX,
"MVAY": OpMVAY,
"MVAV": OpMVAV,
"MVVA": OpMVVA,
"SETA": OpSETA,
"SETX": OpSETX,
"SETY": OpSETY,
"PSHA": OpPSHA,
"POPA": OpPOPA,
"JUMP": OpJUMP,
"JXNZ": OpJXNZ,
"HALT": OpHALT,
"NOOP": OpNOOP,
"OUTA": OpOUTA,
"INCA": OpINCA,
"INCX": OpINCX,
"INCY": OpINCY,
"DECA": OpDECA,
"DECX": OpDECX,
"DECY": OpDECY,
"ADDA": OpADDA,
"MULA": OpMULA,
"MVAX": OpMVAX,
"MVIAX": OpMVIAX,
"MVAY": OpMVAY,
"MVAV": OpMVAV,
"MVVA": OpMVVA,
"SETA": OpSETA,
"SETX": OpSETX,
"SETY": OpSETY,
"PSHA": OpPSHA,
"POPA": OpPOPA,
"JUMP": OpJUMP,
"JXNZ": OpJXNZ,
}

type Word uint64
Expand Down Expand Up @@ -169,6 +171,8 @@ func (g *Machine) Run() {
}
case OpMVAX:
g.X = g.A
case OpMVIAX:
g.X = g.Memory[g.MemOffset+g.A]
case OpMVAY:
g.Y = g.A
case OpMVAV:
Expand Down Expand Up @@ -333,11 +337,16 @@ func assembleInstructionStatement(stmt ast.InstructionStatement, program []Word,

switch instruction {
case "MOVE":
opcodeStr := "MV"
switch operand1 := stmt.Operand1.(type) {
case ast.RegisterLiteral:
if operand1.Dereferenced {
opcodeStr += "I"
}
opcodeStr += operand1.TokenLiteral()
switch operand2 := stmt.Operand2.(type) {
case ast.RegisterLiteral:
opcodeStr := fmt.Sprintf("%s%s%s", "MV", operand1.TokenLiteral(), operand2.TokenLiteral())
opcodeStr += operand2.TokenLiteral()
opcode, ok := opcodes[opcodeStr]
if !ok {
return nil, nil, fmt.Errorf("%w: %s at line %d", ErrUnknownOpcode, opcodeStr, stmt.Token.Line)
Expand All @@ -359,9 +368,10 @@ func assembleInstructionStatement(stmt ast.InstructionStatement, program []Word,
program = append(program, Word(0))
}
case ast.Identifier:
opcodeStr += "V"
switch operand2 := stmt.Operand2.(type) {
case ast.RegisterLiteral:
opcodeStr := fmt.Sprintf("%s%s%s", "MV", "V", operand2.TokenLiteral())
opcodeStr += operand2.TokenLiteral()
opcode, ok := opcodes[opcodeStr]
if !ok {
return nil, nil, fmt.Errorf("%w: %s at line %d", ErrUnknownOpcode, opcodeStr, stmt.Token.Line)
Expand Down
19 changes: 19 additions & 0 deletions gmachine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,25 @@ func TestMOVE_FailsForUnknownIdentifier(t *testing.T) {
}
}

func TestMOVE_CopiesDereferencedRegisterAToRegisterX(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
err := assembleAndRunFromString(g, `
JUMP start
VARB num 42
.start
SETA num
MOVE *A -> X
`)
if err != nil {
t.Fatal("didn't expect an error:", err)
}
var wantX gmachine.Word = 42
if wantX != g.X {
t.Errorf("want %d, got %d", wantX, g.X)
}
}

func TestADDAX(t *testing.T) {
t.Parallel()
g := gmachine.New(nil)
Expand Down
11 changes: 10 additions & 1 deletion parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ func (p *Parser) expectOneOf(tokTypes ...token.TokenType) ast.Expression {
}

switch p.curToken.Type {
case token.ASTERISK:
expr := p.expectOneOf(token.REGISTER)
if expr == nil {
p.errors = append(p.errors, fmt.Errorf("%w: expected one of %+v, got %s at line %d", ErrInvalidSyntax, tokTypes, p.curToken.Type, p.curToken.Line))
return nil
}
regLiteral := expr.(ast.RegisterLiteral)
regLiteral.Dereferenced = true
return regLiteral
case token.REGISTER:
return p.parseRegisterLiteral()
case token.IDENT:
Expand All @@ -123,7 +132,7 @@ func (p *Parser) parseInstructionStatement() ast.Statement {
stmt := ast.InstructionStatement{Token: p.curToken}

if stmt.TokenLiteral() == "MOVE" {
stmt.Operand1 = p.expectOneOf(token.REGISTER, token.IDENT)
stmt.Operand1 = p.expectOneOf(token.ASTERISK, token.REGISTER, token.IDENT)
p.expectOneOf(token.ARROW)
stmt.Operand2 = p.expectOneOf(token.REGISTER, token.IDENT)
}
Expand Down
31 changes: 27 additions & 4 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ func TestParseProgram_ParsesInstructionsWithARegisterLiteralOperands(t *testing.

input := `
MOVE A -> X
MOVE *A -> X
MOVE A -> Y
ADDA X
ADDA Y
Expand Down Expand Up @@ -465,25 +466,33 @@ ADDA Y
Literal: "A",
Line: 3,
},
Dereferenced: true,
},
Operand2: ast.RegisterLiteral{
Token: token.Token{
Type: token.REGISTER,
Literal: "Y",
Literal: "X",
Line: 3,
},
},
},
ast.InstructionStatement{
Token: token.Token{
Type: token.INSTRUCTION,
Literal: "ADDA",
Literal: "MOVE",
Line: 4,
},
Operand1: ast.RegisterLiteral{
Token: token.Token{
Type: token.REGISTER,
Literal: "X",
Literal: "A",
Line: 4,
},
},
Operand2: ast.RegisterLiteral{
Token: token.Token{
Type: token.REGISTER,
Literal: "Y",
Line: 4,
},
},
Expand All @@ -497,11 +506,25 @@ ADDA Y
Operand1: ast.RegisterLiteral{
Token: token.Token{
Type: token.REGISTER,
Literal: "Y",
Literal: "X",
Line: 5,
},
},
},
ast.InstructionStatement{
Token: token.Token{
Type: token.INSTRUCTION,
Literal: "ADDA",
Line: 6,
},
Operand1: ast.RegisterLiteral{
Token: token.Token{
Type: token.REGISTER,
Literal: "Y",
Line: 6,
},
},
},
}

got := program.Statements
Expand Down
2 changes: 1 addition & 1 deletion testdata/gc.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ SETA 42
OUTA

-- want --
0000000 0000 0000 0000 1000 0000 0000 0000 2a00
0000000 0000 0000 0000 1100 0000 0000 0000 2a00
0000010 0000 0000 0000 0300
0000018

0 comments on commit 5262115

Please sign in to comment.