Skip to content

Commit

Permalink
Implemented arithmetic operations for int/float values
Browse files Browse the repository at this point in the history
  • Loading branch information
danielperano committed Dec 21, 2024
1 parent d5a6c24 commit 5a3cd96
Show file tree
Hide file tree
Showing 2 changed files with 248 additions and 30 deletions.
214 changes: 199 additions & 15 deletions Lang/src/main/java/chipmunk/vm/hvm/HvmCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,20 @@ public ChipmunkModule compileModule(BinaryModule module){
while(ip < code.length){
switch (code[ip]){
case PUSH -> ip = push(builder, constants, operands, code, ip);
case ADD -> ip = add(builder, constants, operands, code, ip);
case RETURN -> ip = _return(builder, constants, operands, code, ip);
case ADD -> ip = add(builder, operands, ip);
case MUL -> ip = mul(builder, operands, ip);
case DIV -> ip = div(builder, operands, ip);
case FDIV -> ip = fdiv(builder, operands, ip);
case MOD -> ip = mod(builder, operands, ip);
case POW -> ip = pow(builder, operands, ip);
case INC -> ip = inc(builder, operands, ip);
case DEC -> ip = dec(builder, operands, ip);
case POS -> ip = pos(builder, operands, ip);
case NEG -> ip = neg(builder, operands, ip);
case RETURN -> ip = _return(builder, operands, ip);
default -> {
throw new IllegalArgumentException("Unknown opcode 0x%02X".formatted(code[ip]));
}
}
}

Expand All @@ -62,10 +74,13 @@ public ChipmunkModule compileModule(BinaryModule module){
private int push(Executable.Builder builder, Object[] constants, Operands operands, byte[] code, int ip){
var value = constants[fetchInt(code, ip + 1)];

Operand op = null;
Operand op;
if(value instanceof Integer || value instanceof Long){
op = operands.push(LONG);
}else if(value instanceof Float || value instanceof Double){
}else if(value instanceof Float f){
value = (double) f;
op = operands.push(DOUBLE);
}else if(value instanceof Double){
op = operands.push(DOUBLE);
}else if(value instanceof String){
op = operands.push(STRING_REF);
Expand All @@ -85,15 +100,13 @@ private int push(Executable.Builder builder, Object[] constants, Operands operan
return ip + 5;
}

private int add(Executable.Builder builder, Object[] constants, Operands operands, byte[] code, int ip){
private int add(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

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

switch (a.type()){
switch (wider(a, b)){
case LONG -> {
builder.appendOpcode(Opcodes.ADD(a.register(), a.register(), b.register()));
operands.push(LONG);
Expand All @@ -107,22 +120,193 @@ private int add(Executable.Builder builder, Object[] constants, Operands operand
return ip + 1;
}

private int _return(Executable.Builder builder, Object[] constants, Operands operands, byte[] code, int ip){
builder.appendOpcode(Opcodes.RETURN(operands.pop().register()));
private int mul(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

promoteNarrower(builder, a, b);

switch (wider(a, b)){
case LONG -> {
builder.appendOpcode(Opcodes.MUL(a.register(), a.register(), b.register()));
operands.push(LONG);
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.DMUL(a.register(), a.register(), b.register()));
operands.push(DOUBLE);
}
}

return ip + 1;
}

private int div(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

toDouble(builder, b);
toDouble(builder, a);

builder.appendOpcode(Opcodes.DDIV(a.register(), a.register(), b.register()));
operands.push(DOUBLE);

return ip + 1;
}

private int fdiv(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

toLong(builder, b);
toLong(builder, a);

builder.appendOpcode(Opcodes.DIV(a.register(), a.register(), b.register()));
operands.push(LONG);

return ip + 1;
}

private int mod(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

promoteNarrower(builder, a, b);

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

return ip + 1;
}

private int pow(Executable.Builder builder, Operands operands, int ip){
var b = operands.pop();
var a = operands.pop();

promoteNarrower(builder, a, b);

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

return ip + 1;
}

private int inc(Executable.Builder builder, Operands operands, int ip){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.CADD(a.register(), a.register(), 1L));
operands.push(LONG);
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.DCADD(a.register(), a.register(), 1.0d));
operands.push(DOUBLE);
}
}

return ip + 1;
}

private int dec(Executable.Builder builder, Operands operands, int ip){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.CADD(a.register(), a.register(), -1L));
operands.push(LONG);
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.DCADD(a.register(), a.register(), -1.0d));
operands.push(DOUBLE);
}
}

return ip + 1;
}

protected int promoteType(Executable.Builder builder, Operand a, Operand b, int ip){
private int pos(Executable.Builder builder, Operands operands, int ip){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.ABS(a.register(), a.register()));
operands.push(LONG);
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.DABS(a.register(), a.register()));
operands.push(DOUBLE);
}
}

return ip + 1;
}

private int neg(Executable.Builder builder, Operands operands, int ip){
var a = operands.pop();

switch (a.type()){
case LONG -> {
builder.appendOpcode(Opcodes.NEG(a.register(), a.register()));
operands.push(LONG);
}
case DOUBLE -> {
builder.appendOpcode(Opcodes.DNEG(a.register(), a.register()));
operands.push(DOUBLE);
}
}

return ip + 1;
}

private int _return(Executable.Builder builder, Operands operands, int ip){
var op = operands.pop();
builder.appendOpcode(Opcodes.RETURN(op.register()));
return ip + 1;
}

protected void promoteNarrower(Executable.Builder builder, Operand a, Operand b){
if(a.type() == LONG && b.type() == DOUBLE){
// Promote register with a
builder.appendOpcode(Opcodes.L2D(a.register(), a.register()));
return ip + 1;
}else if(a.type() == DOUBLE && b.type() == LONG){
// Promote register with b
builder.appendOpcode(Opcodes.L2D(b.register(), b.register()));
return ip + 1;
}
return ip;
}

protected void toDouble(Executable.Builder builder, Operand a){
if(a.type() == LONG){
builder.appendOpcode(Opcodes.L2D(a.register(), a.register()));
}
}

protected void toLong(Executable.Builder builder, Operand a){
if(a.type() == DOUBLE){
builder.appendOpcode(Opcodes.D2L(a.register(), a.register()));
}
}

protected HVMType wider(Operand a, Operand b){
if(a.type() == DOUBLE || b.type() == DOUBLE){
return DOUBLE;
}
return LONG;
}

private int fetchInt(byte[] instructions, int ip) {
Expand Down
Loading

0 comments on commit 5a3cd96

Please sign in to comment.