Eliminate the RELOH2 relocation, as it never worked --- the address would be dtrg-experimental-powerpc
authorDavid Given <dg@cowlark.com>
Sat, 17 Sep 2016 10:43:15 +0000 (12:43 +0200)
committerDavid Given <dg@cowlark.com>
Sat, 17 Sep 2016 10:43:15 +0000 (12:43 +0200)
calculated incorrectly because of overflow errors.

Replace it with an extended RELOPPC relocation which understands addis/ori
pairs; add an la pseudoop to the assembler which generates these and the
appropriate relocation. Make good.

--HG--
branch : dtrg-experimental-powerpc-branch

15 files changed:
h/out.h
mach/powerpc/as/mach2.c
mach/powerpc/as/mach3.c
mach/powerpc/as/mach4.c
mach/powerpc/libem/aar4.s
mach/powerpc/libem/cfu8.s
mach/powerpc/libem/cif8.s
mach/powerpc/libem/cuf8.s
mach/powerpc/libem/powerpc.h
mach/powerpc/ncg/table
plat/linuxppc/libsys/_syscall.s
plat/linuxppc/libsys/trap.s
util/amisc/ashow.c
util/led/ack.out.5
util/led/relocate.c

diff --git a/h/out.h b/h/out.h
index 30cb6ba..45289f3 100644 (file)
--- a/h/out.h
+++ b/h/out.h
@@ -66,7 +66,7 @@ struct outname {
 #define RELO2     2                    /* 2 bytes */
 #define RELO4     3                    /* 4 bytes */
 #define RELOPPC    4            /* PowerPC 26-bit address */
-#define RELOH2     5            /* write top 2 bytes of 4 byte word */
+/* relo 5 is unused */
 #define RELOVC4    6            /* VideoCore IV address in 32-bit instruction */
 
 #define RELPC  0x2000                  /* pc relative */
index 43ea8d7..d1a959f 100644 (file)
@@ -80,7 +80,7 @@
 %token <y_word> OP_TO_RA_RB
 %token <y_word> OP_TO_RA_SI
 
-%token <y_word> OP_la
+%token <y_word> OP_LA
 
 /* Other token types */
 
index d7f5161..278a7e6 100644 (file)
@@ -98,7 +98,7 @@
 
 /* Special instructions */
 
-0,     OP_la,                 0,                                       "la",
+0,     OP_LA,                 0,                                       "la",
 
 /* Branch processor instructions (page 20) */
 
index b105aa2..acb4abf 100644 (file)
@@ -58,6 +58,7 @@ operation
        | OP_LEV               u7                         { emit4($1 | ($2<<5)); }
        | OP_LIA               lia                        { emit4($1 | $2); }
        | OP_LIL               lil                        { emit4($1 | $2); }
+       | OP_LA                la                         /* emitted in subrule */
        ;
 
 c
@@ -66,26 +67,12 @@ c
        ;
        
 e16
-       : '<' expr
-       {
-               DOTVAL += 2;
-               newrelo($2.typ, RELOH2 | FIXUPFLAGS);
-               DOTVAL -= 2;
-               $$ = ($2.val >> 16) & 0xFFFF;
-       }
-       | '>' expr
-       {
-               DOTVAL += 2;
-               newrelo($2.typ, RELO2 | FIXUPFLAGS);
-               DOTVAL -= 2;
-               $$ = $2.val & 0xFFFF;
-       }
-       | expr
+       : absexp
        {
-               DOTVAL += 2;
-               newrelo($1.typ, RELO2 | FIXUPFLAGS);
-               DOTVAL -= 2;
-               $$ = $1.val & 0xFFFF;
+               /* Allow signed or unsigned 16-bit values. */
+               if (($1 < -0x8000) || ($1 > 0xffff))
+                       serror("16-bit value out of range");
+               $$ = (uint16_t) $1;
        }
        ;
                
@@ -206,6 +193,15 @@ bda
        }
        ;
        
+la
+       : GPR ',' expr
+       {
+               newrelo($3.typ, RELOPPC | FIXUPFLAGS);
+               emit4((15<<26) | ($1<<21) | (0<<16)  | ($3.val >> 16)); /* addis */
+               emit4((24<<26) | ($1<<21) | ($1<<16) | ($3.val & 0xffff)); /* ori */
+       }
+       ;
+
 lil
        : expr
        {
index 72af86f..33b67e0 100644 (file)
@@ -16,8 +16,7 @@
 
 .define .aar4
 .aar4:
-       addis r0, r0, <.trap_earray
-       ori r0, r0, >.trap_earray
+       la r0, .trap_earray
        mtspr ctr, r0            ! load CTR with trap address
 
        lwz r0, 0(r3)
index 8b60f69..2e082c2 100644 (file)
 
 .define .cfu8
 .cfu8:
-       la(r3, .fd_00000000)
+       la r3, .fd_00000000
        lfd f0, 0(r3)            ! f0 = 0.0
        
        lfd f1, 0(sp)            ! value to be converted
 
-       la(r3, .fd_FFFFFFFF)
+       la r3, .fd_FFFFFFFF
        lfd f3, 0(r3)            ! f3 = 0xFFFFFFFF      
 
-       la(r3, .fd_80000000)
+       la r3, .fd_80000000
        lfd f4, 0(r3)            ! f4 = 0x80000000      
        
        fsel f2, f1, f1, f0
index 01b503e..2e7b48d 100644 (file)
@@ -24,7 +24,7 @@
        
        lfd f0, 0(sp)            ! load value
 
-       la (r3, pivot)
+       la r3, pivot
        lfd f1, 0(r3)            ! load pivot value
        fsub f0, f0, f1          ! adjust
                                 
index 7adbb7b..ea5ec26 100644 (file)
@@ -20,7 +20,7 @@
        
        lfd f0, 0(sp)            ! load value
        
-       la (r3, pivot)
+       la r3, pivot
        lfd f1, 0(r3)            ! load pivot value
        fsub f0, f0, f1          ! adjust
                                 
index ddc4064..3540a68 100644 (file)
@@ -20,4 +20,3 @@
 #define EQ 2
 #define OV 3
        
-#define la(reg, val) addis reg, r0, <val; ori reg, reg, >val
index 356cfe5..742e825 100644 (file)
@@ -262,6 +262,7 @@ INSTRUCTIONS
   fsub            FD:wo, FD:ro, FD:ro.
   fsubs           FS:wo, FS:ro, FS:ro.
   fmr             FS+FD:wo, FS+FD:ro.
+  la              GPRI:wo, LABEL:ro.
   lbzx            GPRI:wo, GPR:ro, GPR:ro.
   lbz             GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
   lfd             FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro.
@@ -353,8 +354,7 @@ MOVES
        from LABEL to GPR
                gen
                        COMMENT("move LABEL->GPR")
-                       addis %2, R0, {HILABEL, %1.adr}
-                       ori %2, %2, {LOLABEL, %1.adr}
+                       la %2, {LABEL, %1.adr}
        
 /* Sign extension */
 
index 122a3a5..ccafe24 100644 (file)
@@ -42,8 +42,7 @@ __syscall:
        bc IFTRUE, GT, 2f
        
 3:
-       addis r4, r0, <_errno
-       ori r4, r4, >_errno
+       la r4, _errno
        stw r3, 0(r4)
        addi r3, r0, -1
        bclr ALWAYS, 0, 0
index 92ec4bd..af36acf 100644 (file)
@@ -65,15 +65,13 @@ EUNIMPL = 63                ! unimplemented em-instruction called
        
        addi r4, r0, 1
        rlwnm r4, r4, r3, 0, 31  ! calculate trap bit
-       addis r5, r0, <.ignmask
-       ori r5, r5, >.ignmask
+       la r5, .ignmask
        lwz r5, 0(r5)            ! load ignore mask
        and. r4, r4, r5          ! compare
        bclr IFFALSE, EQ, 0      ! return if non-zero
        
 1:
-       addis r4, r0, <.trppc
-       ori r4, r4, >.trppc
+       la r4, .trppc
        lwz r5, 0(r4)            ! load user trap routine
        or. r5, r5, r5           ! test
        bc IFTRUE, EQ, fatal     ! if no user trap routine, bail out
@@ -94,8 +92,7 @@ EUNIMPL = 63          ! unimplemented em-instruction called
 
 fatal:
        addi r3, r0, 1
-       addis r4, r0, <message
-       ori r4, r4, >message
+       la r4, message
        addi r5, r0, 6
        addi r0, r0, 4           ! write()
        sc 0
index b11e60e..498ae39 100644 (file)
@@ -140,9 +140,6 @@ showrelo()
        case RELOPPC:
                printf("\tPowerPC 26-bit address\n");
                break;
-       case RELOH2:
-               printf("\ttop 2 bytes of a 4 byte word\n");
-               break;
        case RELOVC4:
                printf("\tVideoCore IV address in 32-bit instruction\n");
                break;
index 8e34c1a..b49b097 100644 (file)
@@ -158,12 +158,11 @@ struct outrelo {
 /*
  * relocation type bits
  */
-#define RELSZ  0x0fffi     /* relocation length */
+#define RELSZ  0x0fff      /* relocation length */
 #define RELO1  0x01            /* 1 byte */
 #define RELO2  0x02            /* 2 bytes */
 #define RELO4  0x03            /* 4 bytes */
 #define RELOPPC        0x04            /* 26-bit PowerPC address */
-#define RELOH2  0x05        /* write top 2 bytes of 4 byte word */
 #define RELOVC4 0x06        /* VideoCore IV address in 32-bit insruction */
 #define RELPC  0x2000          /* pc relative */
 #define RELBR  0x4000          /* High order byte lowest address. */
index b49e1c5..c72965e 100644 (file)
@@ -18,7 +18,7 @@ static char rcsid[] = "$Id$";
 
 #define UBYTE(x)       ((x) & BYTEMASK)
 
-static long read2(char* addr, int type)
+static uint16_t read2(char* addr, int type)
 {
        unsigned short word0, word1;
 
@@ -28,7 +28,7 @@ static long read2(char* addr, int type)
                return (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
 }
 
-static long read4(char* addr, int type)
+static uint32_t read4(char* addr, int type)
 {
        unsigned short word0, word1;
 
@@ -49,7 +49,7 @@ static long read4(char* addr, int type)
  * one of several different ways (depending on what the instruction is).
  */
 
-static long get_vc4_valu(char* addr)
+static uint32_t get_vc4_valu(char* addr)
 {
        uint16_t opcode = read2(addr, 0);
 
@@ -104,11 +104,36 @@ static long get_vc4_valu(char* addr)
        assert(0 && "unrecognised VC4 instruction");
 }
 
+/* PowerPC fixups are complex as we need to patch up to the next two
+ * instructions in one of several different ways, depending on what the
+ * instructions area.
+ */
+
+static uint32_t get_powerpc_valu(char* addr, uint16_t type)
+{
+       uint32_t opcode1 = read4(addr+0, type);
+       uint32_t opcode2 = read4(addr+4, type);
+
+       if ((opcode1 & 0xfc000000) == 0x48000000)
+       {
+               /* branch instruction */
+               return opcode1 & 0x03fffffd;
+       }
+       else if (((opcode1 & 0xfc1f0000) == 0x3c000000) &&
+                ((opcode2 & 0xfc000000) == 0x60000000))
+       {
+               /* addis / ori instruction pair */
+               return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff);
+       }
+
+       assert(0 && "unrecognised PowerPC instruction");
+}
+
 /*
  * The bits in type indicate how many bytes the value occupies and what
  * significance should be attributed to each byte.
  */
-static long getvalu(char* addr, uint16_t type)
+static uint32_t getvalu(char* addr, uint16_t type)
 {
        switch (type & RELSZ) {
        case RELO1:
@@ -118,9 +143,7 @@ static long getvalu(char* addr, uint16_t type)
        case RELO4:
                return read4(addr, type);
        case RELOPPC:
-               return read4(addr, type) & 0x03FFFFFD;
-       case RELOH2:
-               return read2(addr, type) << 16;
+               return get_powerpc_valu(addr, type);
        case RELOVC4:
                return get_vc4_valu(addr);
        default:
@@ -129,7 +152,7 @@ static long getvalu(char* addr, uint16_t type)
        /* NOTREACHED */
 }
 
-static void write2(long valu, char* addr, int type)
+static void write2(uint16_t valu, char* addr, int type)
 {
        unsigned short  word0, word1;
 
@@ -142,7 +165,7 @@ static void write2(long valu, char* addr, int type)
        }
 }
 
-static void write4(long valu, char* addr, int type)
+static void write4(uint32_t valu, char* addr, int type)
 {
        unsigned short  word0, word1;
 
@@ -170,7 +193,7 @@ static void write4(long valu, char* addr, int type)
  * one of several different ways (depending on what the instruction is).
  */
 
-static void put_vc4_valu(char* addr, long value)
+static void put_vc4_valu(char* addr, uint32_t value)
 {
        uint16_t opcode = read2(addr, 0);
 
@@ -220,12 +243,42 @@ static void put_vc4_valu(char* addr, long value)
                assert(0 && "unrecognised VC4 instruction");
 }
 
+/* PowerPC fixups are complex as we need to patch up to the next two
+ * instructions in one of several different ways, depending on what the
+ * instructions area.
+ */
+
+static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type)
+{
+       uint32_t opcode1 = read4(addr+0, type);
+       uint32_t opcode2 = read4(addr+4, type);
+
+       if ((opcode1 & 0xfc000000) == 0x48000000)
+       {
+               /* branch instruction */
+               uint32_t i = opcode1 & ~0x03fffffd;
+               i |= value & 0x03fffffd;
+               write4(i, addr, type);
+       }
+       else if (((opcode1 & 0xfc1f0000) == 0x3c000000) &&
+                ((opcode2 & 0xfc000000) == 0x60000000))
+       {
+               uint16_t hi = value >> 16;
+               uint16_t lo = value & 0xffff;
+
+               write4((opcode1 & 0xffff0000) | hi, addr+0, type);
+               write4((opcode2 & 0xffff0000) | lo, addr+4, type);
+       }
+       else
+               assert(0 && "unrecognised PowerPC instruction");
+}
+
 /*
  * The bits in type indicate how many bytes the value occupies and what
  * significance should be attributed to each byte.
  * We do not check for overflow.
  */
-static putvalu(long valu, char* addr, uint16_t type)
+static putvalu(uint32_t valu, char* addr, uint16_t type)
 {
 
        switch (type & RELSZ) {
@@ -239,14 +292,7 @@ static putvalu(long valu, char* addr, uint16_t type)
                write4(valu, addr, type);
                break;
        case RELOPPC:
-       {
-               long i = read4(addr, type) & ~0x03FFFFFD;
-               i |= valu & 0x03FFFFFD;
-               write4(i, addr, type);
-               break;
-       }
-       case RELOH2:
-               write2(valu>>16, addr, type);
+               put_powerpc_valu(addr, valu, type);
                break;
        case RELOVC4:
                put_vc4_valu(addr, valu);