summaryrefslogtreecommitdiff
path: root/submit/RegisterAllocator.java
diff options
context:
space:
mode:
authorLizzy Hunt <elizabeth.hunt@simponic.xyz>2023-04-10 09:17:11 -0600
committerLizzy Hunt <elizabeth.hunt@simponic.xyz>2023-04-10 09:17:11 -0600
commit5f28f80c4e25a56cd444914c2f0b3da5e7fdb088 (patch)
tree600ad8b1ec5aad5155baf8c0352281054a8e6366 /submit/RegisterAllocator.java
downloadcminus-5f28f80c4e25a56cd444914c2f0b3da5e7fdb088.tar.gz
cminus-5f28f80c4e25a56cd444914c2f0b3da5e7fdb088.zip
Initial commit - building
Diffstat (limited to 'submit/RegisterAllocator.java')
-rw-r--r--submit/RegisterAllocator.java126
1 files changed, 126 insertions, 0 deletions
diff --git a/submit/RegisterAllocator.java b/submit/RegisterAllocator.java
new file mode 100644
index 0000000..ce18b2b
--- /dev/null
+++ b/submit/RegisterAllocator.java
@@ -0,0 +1,126 @@
+/*
+ */
+package submit;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ *
+ *
+ */
+public final class RegisterAllocator {
+
+ // True if t is used
+ private final boolean[] t = new boolean[10];
+ private final boolean[] s = new boolean[8];
+ private final Set<String> used = new HashSet<>();
+
+ public RegisterAllocator() {
+ clearAll();
+ }
+
+ public String getT() {
+ for (int i = 0; i < t.length; ++i) {
+ if (!t[i]) {
+ t[i] = true;
+ String str = "$t" + i;
+ used.add(str);
+ return str;
+ }
+ }
+ return null;
+ }
+
+// public String getS() {
+// for (int i = 0; i < s.length; ++i) {
+// if (!s[i]) {
+// s[i] = true;
+// String str = "$s" + i;
+// used.add(str);
+// return str;
+// }
+// }
+// return null;
+// }
+
+ // Returns the number of bytes used to save the registers
+ public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t, boolean save) {
+ boolean[] r = s;
+ String prefix = "$s";
+ if (!s_or_t) {
+ r = t;
+ prefix = "$t";
+ }
+ String instruction = "sw";
+ if (!save) {
+ instruction = "lw";
+ }
+ int offset = 0;
+ for (int i = 0; i < r.length; ++i) {
+ if (r[i]) {
+ offset -= 4;
+ String str = prefix + i;
+ code.append(instruction).append(" ").append(str).append(" ").append(offset-baseOffset).append("($sp)\n");
+ }
+ }
+ return -offset;
+ }
+
+// public int saveS(StringBuilder code, int baseOffset) {
+// return saveRestore(code, baseOffset, true, true);
+// }
+
+ public int saveT(StringBuilder code, int baseOffset) {
+ return saveRestore(code, baseOffset, false, true);
+ }
+
+// public int restoreS(StringBuilder code, int baseOffset) {
+// return saveRestore(code, baseOffset, true, false);
+// }
+
+ public int restoreT(StringBuilder code, int baseOffset) {
+ return saveRestore(code, baseOffset, false, false);
+ }
+
+ public List<String> getUsed() {
+ return new ArrayList<>(used);
+ }
+
+ /**
+ * Any time you call this method you should seriously consider adding a
+ * corresponding clear() call.
+ *
+ * @return
+ */
+ public String getAny() {
+// String availS = getS();
+// if (availS != null) {
+// return availS;
+// }
+ String t = getT();
+ if (t == null) {
+ throw new RuntimeException("Out of registers");
+ }
+ return t;
+ }
+
+ public void clear(String reg) {
+ if (reg.charAt(1) == 's') {
+ s[Integer.parseInt(reg.substring(2))] = false;
+ } else if (reg.charAt(1) == 't') {
+ t[Integer.parseInt(reg.substring(2))] = false;
+ } else {
+ throw new RuntimeException("Unexpected register in clear");
+ }
+ }
+
+ public void clearAll() {
+ Arrays.fill(t, false);
+ Arrays.fill(s, false);
+ }
+}