From fe5ca5a85f01b494d55d2373d42e06f0e2d75c7c Mon Sep 17 00:00:00 2001
From: David Given <dg@cowlark.com>
Date: Mon, 3 Sep 2018 22:47:41 +0200
Subject: [PATCH] Added li and la instructions.

---
 h/out.h                       |  3 ++-
 mach/mips/as/instructions.dat |  7 ++++---
 mach/mips/as/mach1.c          |  9 ---------
 mach/mips/as/mach2.c          |  3 +++
 mach/mips/as/mach3.c          |  3 +++
 mach/mips/as/mach4.c          | 31 +++++++++++++++++++++++++++++++
 mach/mips/mcg/table           | 20 ++++++++++----------
 7 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/h/out.h b/h/out.h
index 17a4c908c..4176fd341 100644
--- a/h/out.h
+++ b/h/out.h
@@ -68,7 +68,8 @@ struct outname {
 #define RELOPPC      4          /* PowerPC 26-bit address */
 #define RELOPPC_LIS  5          /* PowerPC lis */
 #define RELOVC4      6          /* VideoCore IV address in 32-bit instruction */
-#define RELOMIPS     7          /* MIPS */
+#define RELOMIPS     7          /* MIPS, low half of word or other*/
+#define RELOMIPSHI   8          /* MIPS, high half of word */
 
 #define RELPC	0x2000			/* pc relative */
 #define RELBR	0x4000			/* High order byte lowest address. */
diff --git a/mach/mips/as/instructions.dat b/mach/mips/as/instructions.dat
index bb46958ba..80af89fdc 100644
--- a/mach/mips/as/instructions.dat
+++ b/mach/mips/as/instructions.dat
@@ -9,13 +9,14 @@
 
 # Useful pseudoops.
 
-000000<RS->00000<RD->00000100000 "mov" RD=gpr ',' RS=gpr
+# or RD, RS, zero
+000000<RS->00000<RD->00000100101 "mov" RD=gpr ',' RS=gpr
 
 # Core ALU instructions.
 
 000000<RS-><RT-><RD->00000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr
-001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RT=gpr ',' IMM=e16
-001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RT=gpr ',' IMM=e16
+001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RS=gpr ',' IMM=e16
+001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RS=gpr ',' IMM=e16
 000000<RS-><RT-><RD->00000100001 "addu" RD=gpr ',' RS=gpr ',' RT=gpr
 000000<RS-><RT-><RD->00000100100 "and" RD=gpr ',' RS=gpr ',' RT=gpr
 001100<RS-><RT-><IMM-----------> "andi" RT=gpr ',' RS=gpr ',' IMM=e16
diff --git a/mach/mips/as/mach1.c b/mach/mips/as/mach1.c
index 50f799684..55c6b5507 100644
--- a/mach/mips/as/mach1.c
+++ b/mach/mips/as/mach1.c
@@ -1,12 +1,3 @@
-/*
- * $Source$
- * $State$
- */
-
 /*
  * Do not #include anything here.  Do it in mach/proto/as/comm0.h
  */
-
-void no_hl(void);
-word_t eval_hl(struct expr_t* expr, int token);
-void emit_hl(word_t in);
diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c
index 11886d052..db6a311f8 100644
--- a/mach/mips/as/mach2.c
+++ b/mach/mips/as/mach2.c
@@ -4,6 +4,9 @@
 %token <y_word> FMT3
 %token <y_word> FCOND
 
+%token <y_word> OP_LI
+%token <y_word> OP_LA
+
 %type <y_word> gpr fpr
 %type <y_word> e16 e9
 %type <y_word> u25 u20 u16 u5 u3
diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c
index 45af1c4fd..4e346d742 100644
--- a/mach/mips/as/mach3.c
+++ b/mach/mips/as/mach3.c
@@ -105,5 +105,8 @@
 0,     FMT3,       5,          "l",
 0,     FMT3,       6,          "ps",
 
+0,     OP_LI,      0,          "li",
+0,     OP_LA,      0,          "la",
+
 #include "tokens.y"
 
diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c
index f4d4c5e8d..3cce17e66 100644
--- a/mach/mips/as/mach4.c
+++ b/mach/mips/as/mach4.c
@@ -1,4 +1,35 @@
 #include "rules.y"
+	| OP_LI GPR ',' expr
+	{
+		word_t reg = $2;
+		word_t type = $4.typ & S_TYP;
+		word_t val = $4.val;
+		if (type != S_ABS)
+			serror("li cannot be used with values that need a fixup");
+		
+		if (val == 0)
+			emit4(0x00000025 | (reg<<11)); /* or reg, zero, zero */
+		else if ((val < -0x8000) || (val > 0xffff))
+			emit4(0x24000000 | (reg<<16) | (val & 0xffff)); /* addiu reg, zero, value */
+		else
+		{
+			emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */
+			emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */
+		}
+	}
+	| OP_LA GPR ',' expr
+	{
+		word_t reg = $2;
+		word_t type = $4.typ & S_TYP;
+		word_t val = $4.val;
+
+		if (type != S_ABS)
+			newrelo($4.typ, RELOMIPSHI | FIXUPFLAGS);
+		emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */
+		if (type != S_ABS)
+			newrelo($4.typ, RELOMIPS | FIXUPFLAGS);
+		emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */
+	}
 
 gpr: GPR
 fpr: FPR
diff --git a/mach/mips/mcg/table b/mach/mips/mcg/table
index 53b73fa53..fc69ba7de 100644
--- a/mach/mips/mcg/table
+++ b/mach/mips/mcg/table
@@ -635,15 +635,15 @@ PATTERNS
     ALUR(DIV.I, "divw")
     ALUR(DIVU.I, "divwu")
 
-    ALUR(ASL.I, "sll")
-    ALUC(ASL.I, "sllv")
-    ALUR(ASR.I, "sra")
-    ALUC(ASR.I, "srav")
+    ALUR(ASL.I, "sllv")
+    ALUC(ASL.I, "sll")
+    ALUR(ASR.I, "srav")
+    ALUC(ASR.I, "sra")
 
-    ALUR(LSL.I, "sll")
-    ALUC(LSL.I, "sllv")
-    ALUR(LSR.I, "srl")
-    ALUC(LSR.I, "srlv")
+    ALUR(LSL.I, "sllv")
+    ALUC(LSL.I, "sll")
+    ALUR(LSR.I, "srlv")
+    ALUC(LSR.I, "srl")
 
     out:(int)reg = NEG.I(left:(int)reg)
         emit "neg %out, %left"
@@ -663,11 +663,11 @@ PATTERNS
     ALUCC(EOR.I, "xori")
 
 	out:(int)reg = value:LABEL.I
-		emit "li32 %out, $value"
+		emit "la %out, $value"
 		cost 4;
 
 	out:(int)reg = value:BLOCK.I
-		emit "li32 %out, $value"
+		emit "la %out, $value"
 		cost 4;
 
 	out:(int)reg = value:CONST.I