More opcodes. sti can now cope with non-standard sizes (really need a better
authorDavid Given <dg@cowlark.com>
Sat, 29 Oct 2016 10:48:05 +0000 (12:48 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 29 Oct 2016 10:48:05 +0000 (12:48 +0200)
fix for this). Hack in crude support for mismatched stack pushes and pops (ints
vs longs).

mach/powerpc/mcg/table
mach/proto/mcg/data.c
mach/proto/mcg/treebuilder.c
util/mcgg/ir.dat

index 3cfb144..366b16d 100644 (file)
@@ -229,7 +229,7 @@ PATTERNS
     out:(int)reg = FPTOLB.I(in:(int)reg)
         with %out == %in
         cost 1;
-        
+
     out:(int)reg = GETSP.I
         emit "mr %out, sp"
         cost 4;
@@ -417,6 +417,19 @@ PATTERNS
         emit "bl .fromui2d"
         cost 4;
 
+    out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg)
+        emit "mr %out.0, %in1"
+        emit "mr %out.1, %in2"
+        cost 8;
+    
+    out:(int)reg = FROML0.I(in:(long)reg)
+        emit "mr %out, %in.0"
+        cost 4;
+
+    out:(int)reg = FROML1.I(in:(long)reg)
+        emit "mr %out, %in.1"
+        cost 4;
+
 
 
 /* Locals */
@@ -448,6 +461,11 @@ PATTERNS
                emit "b $addr"
                cost 4;
 
+    JUMP(dest:(int)reg)
+        emit "mtspr ctr, %dest"
+        emit "bcctrl 20, 0, 0"
+        cost 8;
+
        CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
         emit "bc 12, 2, $true" /* IFTRUE EQ */
                emit "b $false"
index 2e6fde9..5eeca8f 100644 (file)
@@ -64,7 +64,8 @@ void data_float(const char* data, size_t size, bool is_ro)
        emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
     assert((size == 4) || (size == 8));
 
-    if (float_cst(data, size, (char*) buffer))
+    i = float_cst(data, size, (char*) buffer);
+    if ((i != 0) && (i != 2)) /* 2 == overflow */
         fatal("cannot parse floating point constant %s sz %d", data, size);
 
     fprintf(outputfile, "\t!float %s sz %d\n", data, size);
index 73e454d..1d0c408 100644 (file)
@@ -59,7 +59,37 @@ static struct ir* pop(int size)
 #endif
 
         if (ir->size != size)
-            fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
+        {
+            if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize))
+            {
+                /* Tried to read a long, but we got an int. Assemble the long
+                 * out of two ints. Note that EM doesn't specify an order. */
+                return
+                    new_ir2(
+                        IR_FROMIPAIR, size,
+                        ir,
+                        pop(EM_wordsize)
+                    );
+            }
+            else if ((size == EM_wordsize) && (ir->size == (EM_wordsize*2)))
+            {
+                /* Tried to read an int, but we got a long. */
+                push(
+                    new_ir1(
+                        IR_FROML1, EM_wordsize,
+                        ir
+                    )
+                );
+
+                return
+                    new_ir1(
+                        IR_FROML0, EM_wordsize,
+                        ir
+                    );
+            }
+            else
+                fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
+        }
         return ir;
     }
 }
@@ -864,15 +894,34 @@ static void insn_ivalue(int opcode, arith value)
         case op_sti:
         {
             struct ir* ptr = pop(EM_pointersize);
-            struct ir* val = pop(value);
+            int offset = 0;
 
-            appendir(
-                store(
-                    value,
-                    ptr, 0,
-                    val
-                )
-            );
+            /* FIXME: this is awful; need a better way of dealing with
+             * non-standard EM sizes. */
+            if (value > (EM_wordsize*2))
+                appendir(ptr);
+
+            while (value > 0)
+            {
+                int s;
+                if (value > (EM_wordsize*2))
+                    s = EM_wordsize*2;
+                else
+                    s = value;
+
+                appendir(
+                    store(
+                        s,
+                        ptr, offset,
+                        pop(s)
+                    )
+                );
+
+                value -= s;
+                offset += s;
+            }
+
+            assert(value == 0);
             break;
         }
 
@@ -1483,6 +1532,31 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             );
             break;
 
+        case op_gto:
+        {
+            struct ir* descriptor = pop(EM_pointersize);
+
+            appendir(
+                new_ir1(
+                    IR_SETSP, EM_pointersize,
+                    load(EM_pointersize, descriptor, EM_pointersize*2)
+                )
+            );
+            appendir(
+                new_ir1(
+                    IR_SETFP, EM_pointersize,
+                    load(EM_pointersize, descriptor, EM_pointersize*1)
+                )
+            );
+            appendir(
+                new_ir1(
+                    IR_JUMP, 0,
+                    load(EM_pointersize, descriptor, EM_pointersize*0)
+                )
+            );
+            break;
+        }
+
         case op_fil:
         {
             /* Set filename --- ignore. */
index 92fb5df..1db593e 100644 (file)
@@ -71,6 +71,9 @@ S ?=I. FROMSI
 S ?=L. FROMSL
 S ?=F. FROMF
 S ?=D. FROMD
+S L=II FROMIPAIR
+S I=L. FROML0
+S I=L. FROML1
 
 # The H versions are only used if wordsize > 2
 S I=I. EXTENDB