98 lines
3.5 KiB
Java
98 lines
3.5 KiB
Java
package cd.backend.codegen;
|
|
|
|
import cd.backend.codegen.RegisterManager.Register;
|
|
|
|
import static cd.backend.codegen.Interrupts.Mem.BUFFER;
|
|
|
|
public class Interrupts {
|
|
|
|
protected static final int EXIT_OK = 0, EXIT_DIV_0 = 7, EXIT_INPUT_MISMATCH = 8;
|
|
protected static final int STDIN = 0, STDOUT = 1, STDERR = 2;
|
|
protected static final int I_EXIT = 1, I_READ = 3, I_WRITE = 4;
|
|
|
|
protected enum Mem {
|
|
BUFFER("io_buffer"), EAX("eax");
|
|
|
|
String pos;
|
|
Mem(String pos) {
|
|
this.pos = pos;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return pos;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write auxiliary data variables needed for I/O and division
|
|
* @param cg AstCodeGenerator to print instructions
|
|
*/
|
|
protected static void reserveMemory(AstCodeGenerator cg) {
|
|
for (Mem m : Mem.values()) {
|
|
cg.emit.emitLabel(m.pos);
|
|
cg.emit.emitConstantData("0");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes a single character passed as parameter
|
|
* @param cg AstCodeGenerator to print instructions
|
|
* @param i Character code in ASCII (or single casted character)
|
|
*/
|
|
protected static void printChar(AstCodeGenerator cg, int i) {
|
|
cg.emit.emitMove(AssemblyEmitter.constant(i), BUFFER.pos);
|
|
printChar(cg);
|
|
}
|
|
|
|
/**
|
|
* Writes a single character from the BUFFER memory pos to stdout
|
|
* @param cg AstCodeGenerator to print instructions
|
|
*/
|
|
protected static void printChar(AstCodeGenerator cg) {
|
|
Register[] needed = {Register.EAX, Register.EBX, Register.ECX, Register.EDX};
|
|
for (int i = 0; i < needed.length; i++)
|
|
if (cg.rm.isInUse(needed[i]))
|
|
cg.emit.emit("push", needed[i]);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(I_WRITE), Register.EAX);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(STDOUT), Register.EBX);
|
|
cg.emit.emitMove("$" + BUFFER.pos, Register.ECX);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(1), Register.EDX);
|
|
cg.emit.emit("int", 0x80);
|
|
for (int i = needed.length - 1; i >= 0; i--)
|
|
if (cg.rm.isInUse(needed[i]))
|
|
cg.emit.emit("pop", needed[i]);
|
|
}
|
|
|
|
/**
|
|
* Reads a single character from stdin and places it in the
|
|
* memory pos BUFFER
|
|
*/
|
|
protected static void readChar(AstCodeGenerator cg, Register destination) {
|
|
Register[] needed = {Register.EAX, Register.EBX, Register.ECX, Register.EDX};
|
|
for (int i = 0; i < needed.length; i++)
|
|
if (cg.rm.isInUse(needed[i]))
|
|
cg.emit.emit("push", needed[i]);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(I_READ), Register.EAX);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(STDIN), Register.EBX);
|
|
cg.emit.emitMove("$" + BUFFER.pos, Register.ECX);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(1), Register.EDX);
|
|
cg.emit.emit("int", 0x80);
|
|
for (int i = needed.length - 1; i >= 0; i--)
|
|
if (cg.rm.isInUse(needed[i]))
|
|
cg.emit.emit("pop", needed[i]);
|
|
cg.emit.emitMove(BUFFER.pos, destination);
|
|
}
|
|
|
|
/**
|
|
* Generates a exit interrupt with the code provided
|
|
* @param cg AstCodeGenerator to print instructions
|
|
* @param exitCode Number to use as exit code (can use constants in this class)
|
|
*/
|
|
protected static void exit(AstCodeGenerator cg, int exitCode) {
|
|
cg.emit.emitMove(AssemblyEmitter.constant(I_EXIT), Register.EAX);
|
|
cg.emit.emitMove(AssemblyEmitter.constant(exitCode), Register.EBX);
|
|
cg.emit.emit("int", 0x80);
|
|
}
|
|
}
|