Skip to content

Commit

Permalink
Cleaned up register/operand handling, implemented a few math opcodes
Browse files Browse the repository at this point in the history
  • Loading branch information
danielperano committed Dec 20, 2024
1 parent ec5074f commit f393203
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 41 deletions.
166 changes: 141 additions & 25 deletions Lang/src/main/java/chipmunk/compiler/assembler/HVMAssembler.java
Original file line number Diff line number Diff line change
@@ -1,56 +1,172 @@
package chipmunk.compiler.assembler;

import myworld.hummingbird.Executable;
import myworld.hummingbird.Opcode;
import myworld.hummingbird.Opcodes;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.nio.charset.StandardCharsets;

import static chipmunk.compiler.assembler.HVMType.*;

public class HVMAssembler {

private final Stack<HVMType> types = new Stack<>();
private final RegisterAllocator registers = new RegisterAllocator();
private final Operands operands = new Operands();
protected final Executable.Builder builder = new Executable.Builder();

public void push(Object value){
Operand op = null;
if(value instanceof Integer || value instanceof Long){
types.push(HVMType.LONG);
op = operands.push(LONG);
}else if(value instanceof Float || value instanceof Double){
types.push(HVMType.DOUBLE);
op = operands.push(DOUBLE);
}else if(value instanceof String){
types.push(HVMType.STRING_REF);
op = operands.push(STRING_REF);
}else{
// TODO - invalid constant type
}

// TODO - Strings have to be encoded in the data section, with the address pushed as a constant.
builder.appendOpcode(Opcodes.CONST(0, value)); // TODO - register allocation
if(op.type() == HVMType.STRING_REF){
// Strings have to be encoded in the data section, with the address pushed as a constant.
value = builder.appendData(value.toString().getBytes(StandardCharsets.UTF_8));
}
builder.appendOpcode(Opcodes.CONST(op.register(), value));
}

public void add(){
// TODO - for each Chipmunk opcode we have to inspect the HVM operand types and select the
// opcode to use, possibly emitting conversion opcodes (converting longs to doubles, for example).
var a = types.pop();
var b = types.pop();
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.ADD(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DADD(a.register(), a.register(), b.register()));
}
}

public void sub(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.SUB(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DSUB(a.register(), a.register(), b.register()));
}
}

public void mul(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a){
case LONG -> builder.appendOpcode(Opcodes.ADD(registers.pushRegister(), 0, 0));
case DOUBLE -> builder.appendOpcode(Opcodes.DADD(registers.pushRegister(), 0, 0));
switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.MUL(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DMUL(a.register(), a.register(), b.register()));
}
}

public void div(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.DIV(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DDIV(a.register(), a.register(), b.register()));
}
}

public void fdiv(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

// TODO - floor division
switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.DIV(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DDIV(a.register(), a.register(), b.register()));
}
}

public void mod(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.REM(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DREM(a.register(), a.register(), b.register()));
}
}

public void pow(){
var b = operands.pop();
var a = operands.pop();

if(a != b){
promoteType(a, b);
}

switch (a.type()){
case LONG -> builder.appendOpcode(Opcodes.POW(a.register(), a.register(), b.register()));
case DOUBLE -> builder.appendOpcode(Opcodes.DPOW(a.register(), a.register(), b.register()));
}
}

public void inc(){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.CONST(a.register() + 1, 1));
builder.appendOpcode(Opcodes.ADD(a.register(), a.register(), a.register() + 1));
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.CONST(a.register() + 1, 1.0d));
builder.appendOpcode(Opcodes.DADD(a.register(), a.register(), a.register() + 1));
}
}
}

public void dec(){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.CONST(a.register() + 1, 1));
builder.appendOpcode(Opcodes.SUB(a.register(), a.register(), a.register() + 1));
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.CONST(a.register() + 1, 1.0d));
builder.appendOpcode(Opcodes.DSUB(a.register(), a.register(), a.register() + 1));
}
}
}

protected void promoteType(HVMType a, HVMType b){
if(a == HVMType.LONG && b == HVMType.DOUBLE){
// TODO - promote register with a
builder.appendOpcode(Opcodes.L2D(0, 0));
}else if(a == HVMType.DOUBLE && b == HVMType.LONG){
// TODO - promote register with b
builder.appendOpcode(Opcodes.L2D(0, 0));
protected void promoteType(Operand a, Operand b){
if(a.type() == LONG && b.type() == DOUBLE){
// Promote register with a
builder.appendOpcode(Opcodes.L2D(a.register(), a.register()));
}else if(a.type() == DOUBLE && b.type() == LONG){
// Promote register with b
builder.appendOpcode(Opcodes.L2D(b.register(), b.register()));
}
}

Expand Down
23 changes: 23 additions & 0 deletions Lang/src/main/java/chipmunk/compiler/assembler/Operand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2024 MyWorld, LLC
* All rights reserved.
*
* This file is part of Chipmunk.
*
* Chipmunk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chipmunk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chipmunk. If not, see <https://www.gnu.org/licenses/>.
*/

package chipmunk.compiler.assembler;

public record Operand(int register, HVMType type) {}
38 changes: 38 additions & 0 deletions Lang/src/main/java/chipmunk/compiler/assembler/Operands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2024 MyWorld, LLC
* All rights reserved.
*
* This file is part of Chipmunk.
*
* Chipmunk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chipmunk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chipmunk. If not, see <https://www.gnu.org/licenses/>.
*/

package chipmunk.compiler.assembler;

import java.util.Stack;

public class Operands {

protected Stack<HVMType> types = new Stack<>();

public Operand push(HVMType type){
types.push(type);
return new Operand(types.size() - 1, type);
}

public Operand pop(){
return new Operand(types.size() - 1, types.pop());
}

}

This file was deleted.

0 comments on commit f393203

Please sign in to comment.