aboutsummaryrefslogtreecommitdiff
path: root/snug-clean/src/MIPS/MIPS32.icl
diff options
context:
space:
mode:
Diffstat (limited to 'snug-clean/src/MIPS/MIPS32.icl')
-rw-r--r--snug-clean/src/MIPS/MIPS32.icl162
1 files changed, 162 insertions, 0 deletions
diff --git a/snug-clean/src/MIPS/MIPS32.icl b/snug-clean/src/MIPS/MIPS32.icl
new file mode 100644
index 0000000..a124007
--- /dev/null
+++ b/snug-clean/src/MIPS/MIPS32.icl
@@ -0,0 +1,162 @@
+implementation module MIPS.MIPS32
+
+import StdEnv
+
+import Text
+
+instance toString Line
+where
+ toString (StartSection s) = "\t." +++ s
+ toString (Align i) = "\t.align\t" +++ toString i
+ toString (Label l) = l +++ ":"
+ toString (Instr i) = "\t" +++ toString i
+ toString (RawWord i) = "\t.word\t" +++ toString i
+ toString (RawAscii s) = concat3 "\t.ascii\t\"" s "\"" // TODO: escaping
+
+instance toString Instruction
+where
+ toString (LoadByte signed rt offset base) =
+ memInstrS (if (signed=:Signed) "lb" "lbu") rt (checkOffset offset) base
+ toString (LoadHalfword signed rt offset base) =
+ memInstrS (if (signed=:Signed) "lh" "lhu") rt (checkOffset offset) base
+ toString (LoadWord rt offset base) =
+ memInstrS "lw" rt (checkOffset offset) base
+ toString (StoreByte rt offset base) =
+ memInstrS "sb" rt (checkOffset offset) base
+ toString (StoreHalfword rt offset base) =
+ memInstrS "sh" rt (checkOffset offset) base
+ toString (StoreWord rt offset base) =
+ memInstrS "sw" rt (checkOffset offset) base
+
+ toString (AddImmediate signed rt rs imm) =
+ immediateInstrS (if (signed=:Signed) "addi" "addiu") rt rs (checkImmediate signed imm)
+ toString (AndImmediate rt rs imm) =
+ immediateInstrS "andi" rt rs (checkImmediate Unsigned imm)
+ toString (LoadUpperImmediate rt imm) =
+ concat ["lui\t",toString rt,",",toString (checkImmediate Unsigned imm)]
+ toString (OrImmediate rt rs imm) =
+ immediateInstrS "ori" rt rs (checkImmediate Unsigned imm)
+ toString (XorImmediate rt rs imm) =
+ immediateInstrS "xori" rt rs (checkImmediate Unsigned imm)
+
+ toString (AddWord signed rd rs rt) =
+ threeRegInstrS (if (signed=:Signed) "add" "addu") rd rs rt
+ toString (AndWord rd rs rt) =
+ threeRegInstrS "and" rd rs rt
+ toString (NorWord rd rs rt) =
+ threeRegInstrS "nor" rd rs rt
+ toString (OrWord rd rs rt) =
+ threeRegInstrS "or" rd rs rt
+ toString (SubWord signed rd rs rt) =
+ threeRegInstrS (if (signed=:Signed) "sub" "subu") rd rs rt
+ toString (XorWord rd rs rt) =
+ threeRegInstrS "xor" rd rs rt
+
+ toString (Jump link target) =
+ instr +++ toString target
+ where
+ instr = case (link, target) of
+ (NoLink, Direct _) -> "j\t"
+ (Link, Direct _) -> "jal\t"
+ (NoLink, Register _) -> "jr\t"
+ (Link, Register _) -> "jalr\t"
+ toString (BranchOn1 (BCGeZero link) rs offset) =
+ branch1InstrS (if (link=:Link) "bgezal" "bgez") rs (checkOffset offset)
+ toString (BranchOn1 BCGtZero rs offset) =
+ branch1InstrS "bgtz" rs (checkOffset offset)
+ toString (BranchOn1 BCLeZero rs offset) =
+ branch1InstrS "blez" rs (checkOffset offset)
+ toString (BranchOn1 (BCLtZero link) rs offset) =
+ branch1InstrS (if (link=:Link) "bltzal" "bltz") rs (checkOffset offset)
+ toString (BranchOn2 cond rs rt offset) =
+ immediateInstrS (if (cond=:BCEq) "beq" "bne") rs rt (Immediate (checkOffset offset))
+
+ toString (Break arg) =
+ "break\t" +++ toString arg
+ toString (Syscall arg) =
+ "syscall\t" +++ toString arg
+
+ toString (LoadAddress rd imm) =
+ concat4 "la\t" (toString rd) "," (toString imm)
+ toString Nop =
+ "nop"
+
+instance toString JumpTarget
+where
+ toString (Direct imm)
+ = toString imm
+ toString (Register r)
+ = toString r
+
+instance toString Immediate
+where
+ toString (Immediate i)
+ = toString i
+ toString (Address offset label)
+ | offset == 0
+ = label
+ | offset > 0
+ = concat3 label "+" (toString offset)
+ = concat3 label "-" (toString offset)
+
+memInstrS :: !String !Register !Offset !Base -> String
+memInstrS opcode rt 0 base = concat [opcode,"\t",toString rt,",(",toString base,")"]
+memInstrS opcode rt offset base = concat [opcode,"\t",toString rt,",",toString offset,"(",toString base,")"]
+
+immediateInstrS :: !String !TargetRegister !SourceRegister !Immediate -> String
+immediateInstrS opcode rt rs imm = concat [opcode,"\t",toString rt,",",toString rs,",",toString imm]
+
+threeRegInstrS :: !String !DestinationRegister !SourceRegister !TargetRegister -> String
+threeRegInstrS opcode rd rs rt = concat [opcode,"\t",toString rd,",",toString rs,",",toString rt]
+
+branch1InstrS :: !String !SourceRegister !Offset -> String
+branch1InstrS opcode rs offset = concat [opcode,"\t",toString rs,",",toString offset]
+
+instance toString Register
+where
+ toString reg = toString` (checkReg reg)
+ where
+ /* Sorted by estimated frequency for efficiency */
+ toString` (T n) = "$t" +++ toString n
+ toString` (S n) = "$s" +++ toString n
+ toString` (A n) = "$a" +++ toString n
+ toString` R0 = "$0"
+ toString` GP = "$gp"
+ toString` SP = "$sp"
+ toString` FP = "$fp"
+ toString` RA = "$ra"
+ toString` AT = "$at"
+ toString` V0 = "$v0"
+ toString` V1 = "$v1"
+ toString` K0 = "$k0"
+ toString` K1 = "$k1"
+
+checkReg :: !Register -> Register
+checkReg (T n) | not (0 <= n && n <= 9)
+ = abort ("non-existing register $t" +++ toString n +++ "\n")
+checkReg (S n) | not (0 <= n && n <= 7)
+ = abort ("non-existing register $s" +++ toString n +++ "\n")
+checkReg (A n) | not (0 <= n && n <= 3)
+ = abort ("non-existing register $a" +++ toString n +++ "\n")
+checkReg reg
+ = reg
+
+checkOffset :: !Int -> Int
+checkOffset offset
+ | 0 <= offset && offset <= 0x7fff
+ = offset
+ | offset >= -0x8000
+ = offset bitand 0xffff
+ = abort ("offset " +++ toString offset +++ " out of bounds\n")
+
+checkImmediate :: !Signedness !Immediate -> Immediate
+checkImmediate Signed (Immediate imm)
+ | 0 <= imm && imm <= 0x7fff
+ = Immediate imm
+ | imm >= -0x8000
+ = Immediate (imm bitand 0xffff)
+ = abort ("signed immediate " +++ toString imm +++ " out of bounds\n")
+checkImmediate Unsigned (Immediate imm)
+ | 0 <= imm && imm <= 0xffff
+ = Immediate imm
+ = abort ("unsigned immediate " +++ toString imm +++ " out of bounds\n")