https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67443

--- Comment #8 from Dominik Vogt <vogt at linux dot vnet.ibm.com> ---
Snippet of the assembly code from the test program posted in comment 4:

good compiler:
==============

# r1 is 0x******XX (XX = value to store in the f1 field)
# r3 is the target address (ps)
# r9 is 0x**YYYYYY (YYYYYY = value to store in the f2 field)

  l       %r2,.L25-.L24(%r13) # r2 := (uint32)0xff000000
  stc     %r1,0(%r3)          # 8-bit-store *(char *)ps := (r1 & 0xff)
                              # -> ps: XX ** ** **
  lr      %r1,%r9             # 32-bit-load r1 := r9 -> r1 = 0x**YYYYYY
  n       %r2,0(%r3)          # 32-bit-and r2 := r2 & *(uint32 *)ps
                              # -> r2 = 0xXX000000
  nilh    %r1,255             # 16-bit-and of bits 32-47 of r1 with 0x00ff,
i.e.
                              # it zeroes the top 8 bits -> r1 = 0x00YYYYYY 
  or      %r1,%r2             # 32-bit or r1 := r1 | r2 -> 0xXX00YYYY
  st      %r1,0(%r3)          # 32-bit store *(uint32)ps := r1
                              # -> ps: XX YY YY YY

.L24:
.L25:
  .long   -16777216

bad compiler:
=============

The stc instruction is missing, so the resulting structure has a bad value in
f1.

--

This is the modified program I used for debugging, compiled with

  $ g++ -O2 -march=z900 -fPIC -std=gnu++11 t67443.cxx

---
#include <stdio.h> 

__attribute__ ((noinline)) bool f(void *s) { return s ? true : false; } 
int *gt; 
struct s_t 
{ 
  unsigned f1: 8; 
  unsigned f2: 24; 
}; 
__attribute__ ((noinline)) 
bool foo(int a, int **pp, s_t **pps, void *s, int **x) 
{ 
  s_t *ps = *pps; 

  if (!f(x)) 
    return false; 
  unsigned i = **pp; 
  volatile register long r2 __asm__ ("r2") = 1; 
  if (**pp >= 999 && **x < 77) 
    { 
      ps->f1 = **x; 
      ps->f2 = **pp; 
    } 
  f(s); 
  int y; 
  do { y &= *gt; } while (y != 0); 
  __asm__ __volatile__ ("" : : : "memory", "r2","r3","r4","r5"); 
  int z; 
  do { z &= *gt; } while (z != 0); 
  return i && x && ps && s; 
} 

int main(void) 
{ 
  int i1 = 999; 
  int *pi1 = &i1; 
  s_t st; 
  s_t *pst = &st; 
  int x = 55; 
  int *px = &x; 
  int t = 0; 

  gt = &t; 
  foo(1, &pi1, &pst, 0, &px); 
  fprintf(stderr, "f1 %u, f2 %u\n", (unsigned int)st.f1, (unsigned int)st.f2); 
} 
---

This prints "55 999" for the good compiler (correct) and "255 999" for the bad
compiler (wrong).

Reply via email to