Commit 8384dd67fec5652a09ada4576214abfafab32c0c

Authored by blueswir1
1 parent a8c768c0

Implement byte swapping accesses

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4574 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -233,6 +233,15 @@ static inline int lduw_le_p(void *ptr) @@ -233,6 +233,15 @@ static inline int lduw_le_p(void *ptr)
233 int val; 233 int val;
234 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); 234 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
235 return val; 235 return val;
  236 +#elif defined(__sparc__)
  237 +#ifndef ASI_PRIMARY_LITTLE
  238 +#define ASI_PRIMARY_LITTLE 0x88
  239 +#endif
  240 +
  241 + int val;
  242 + __asm__ __volatile__ ("lduha [%1] %2, %0" : "=r" (val) : "r" (ptr),
  243 + "i" (ASI_PRIMARY_LITTLE));
  244 + return val;
236 #else 245 #else
237 uint8_t *p = ptr; 246 uint8_t *p = ptr;
238 return p[0] | (p[1] << 8); 247 return p[0] | (p[1] << 8);
@@ -245,6 +254,11 @@ static inline int ldsw_le_p(void *ptr) @@ -245,6 +254,11 @@ static inline int ldsw_le_p(void *ptr)
245 int val; 254 int val;
246 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); 255 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
247 return (int16_t)val; 256 return (int16_t)val;
  257 +#elif defined(__sparc__)
  258 + int val;
  259 + __asm__ __volatile__ ("ldsha [%1] %2, %0" : "=r" (val) : "r" (ptr),
  260 + "i" (ASI_PRIMARY_LITTLE));
  261 + return val;
248 #else 262 #else
249 uint8_t *p = ptr; 263 uint8_t *p = ptr;
250 return (int16_t)(p[0] | (p[1] << 8)); 264 return (int16_t)(p[0] | (p[1] << 8));
@@ -257,6 +271,11 @@ static inline int ldl_le_p(void *ptr) @@ -257,6 +271,11 @@ static inline int ldl_le_p(void *ptr)
257 int val; 271 int val;
258 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr)); 272 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
259 return val; 273 return val;
  274 +#elif defined(__sparc__)
  275 + int val;
  276 + __asm__ __volatile__ ("lduwa [%1] %2, %0" : "=r" (val) : "r" (ptr),
  277 + "i" (ASI_PRIMARY_LITTLE));
  278 + return val;
260 #else 279 #else
261 uint8_t *p = ptr; 280 uint8_t *p = ptr;
262 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 281 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
@@ -265,17 +284,27 @@ static inline int ldl_le_p(void *ptr) @@ -265,17 +284,27 @@ static inline int ldl_le_p(void *ptr)
265 284
266 static inline uint64_t ldq_le_p(void *ptr) 285 static inline uint64_t ldq_le_p(void *ptr)
267 { 286 {
  287 +#if defined(__sparc__)
  288 + uint64_t val;
  289 + __asm__ __volatile__ ("ldxa [%1] %2, %0" : "=r" (val) : "r" (ptr),
  290 + "i" (ASI_PRIMARY_LITTLE));
  291 + return val;
  292 +#else
268 uint8_t *p = ptr; 293 uint8_t *p = ptr;
269 uint32_t v1, v2; 294 uint32_t v1, v2;
270 v1 = ldl_le_p(p); 295 v1 = ldl_le_p(p);
271 v2 = ldl_le_p(p + 4); 296 v2 = ldl_le_p(p + 4);
272 return v1 | ((uint64_t)v2 << 32); 297 return v1 | ((uint64_t)v2 << 32);
  298 +#endif
273 } 299 }
274 300
275 static inline void stw_le_p(void *ptr, int v) 301 static inline void stw_le_p(void *ptr, int v)
276 { 302 {
277 #ifdef __powerpc__ 303 #ifdef __powerpc__
278 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr)); 304 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
  305 +#elif defined(__sparc__)
  306 + __asm__ __volatile__ ("stha %1, [%2] %3" : "=m" (*(uint16_t *)ptr) : "r" (v),
  307 + "r" (ptr), "i" (ASI_PRIMARY_LITTLE));
279 #else 308 #else
280 uint8_t *p = ptr; 309 uint8_t *p = ptr;
281 p[0] = v; 310 p[0] = v;
@@ -287,6 +316,9 @@ static inline void stl_le_p(void *ptr, int v) @@ -287,6 +316,9 @@ static inline void stl_le_p(void *ptr, int v)
287 { 316 {
288 #ifdef __powerpc__ 317 #ifdef __powerpc__
289 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); 318 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
  319 +#elif defined(__sparc__)
  320 + __asm__ __volatile__ ("stwa %1, [%2] %3" : "=m" (*(uint32_t *)ptr) : "r" (v),
  321 + "r" (ptr), "i" (ASI_PRIMARY_LITTLE));
290 #else 322 #else
291 uint8_t *p = ptr; 323 uint8_t *p = ptr;
292 p[0] = v; 324 p[0] = v;
@@ -298,9 +330,15 @@ static inline void stl_le_p(void *ptr, int v) @@ -298,9 +330,15 @@ static inline void stl_le_p(void *ptr, int v)
298 330
299 static inline void stq_le_p(void *ptr, uint64_t v) 331 static inline void stq_le_p(void *ptr, uint64_t v)
300 { 332 {
  333 +#if defined(__sparc__)
  334 + __asm__ __volatile__ ("stxa %1, [%2] %3" : "=m" (*(uint64_t *)ptr) : "r" (v),
  335 + "r" (ptr), "i" (ASI_PRIMARY_LITTLE));
  336 +#undef ASI_PRIMARY_LITTLE
  337 +#else
301 uint8_t *p = ptr; 338 uint8_t *p = ptr;
302 stl_le_p(p, (uint32_t)v); 339 stl_le_p(p, (uint32_t)v);
303 stl_le_p(p + 4, v >> 32); 340 stl_le_p(p + 4, v >> 32);
  341 +#endif
304 } 342 }
305 343
306 /* float access */ 344 /* float access */
tcg/sparc/tcg-target.c
@@ -178,6 +178,7 @@ static inline int tcg_target_const_match(tcg_target_long val, @@ -178,6 +178,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
178 #define INSN_RD(x) ((x) << 25) 178 #define INSN_RD(x) ((x) << 25)
179 #define INSN_RS1(x) ((x) << 14) 179 #define INSN_RS1(x) ((x) << 14)
180 #define INSN_RS2(x) (x) 180 #define INSN_RS2(x) (x)
  181 +#define INSN_ASI(x) ((x) << 5)
181 182
182 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) 183 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
183 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff) 184 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
@@ -242,6 +243,21 @@ static inline int tcg_target_const_match(tcg_target_long val, @@ -242,6 +243,21 @@ static inline int tcg_target_const_match(tcg_target_long val,
242 #define STH (INSN_OP(3) | INSN_OP3(0x06)) 243 #define STH (INSN_OP(3) | INSN_OP3(0x06))
243 #define STW (INSN_OP(3) | INSN_OP3(0x04)) 244 #define STW (INSN_OP(3) | INSN_OP3(0x04))
244 #define STX (INSN_OP(3) | INSN_OP3(0x0e)) 245 #define STX (INSN_OP(3) | INSN_OP3(0x0e))
  246 +#define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
  247 +#define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
  248 +#define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
  249 +#define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
  250 +#define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
  251 +#define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
  252 +#define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
  253 +#define STBA (INSN_OP(3) | INSN_OP3(0x15))
  254 +#define STHA (INSN_OP(3) | INSN_OP3(0x16))
  255 +#define STWA (INSN_OP(3) | INSN_OP3(0x14))
  256 +#define STXA (INSN_OP(3) | INSN_OP3(0x1e))
  257 +
  258 +#ifndef ASI_PRIMARY_LITTLE
  259 +#define ASI_PRIMARY_LITTLE 0x88
  260 +#endif
245 261
246 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2, 262 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
247 int op) 263 int op)
@@ -332,6 +348,14 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, in @@ -332,6 +348,14 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, in
332 } 348 }
333 } 349 }
334 350
  351 +static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
  352 + int offset, int op, int asi)
  353 +{
  354 + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
  355 + tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
  356 + INSN_ASI(asi) | INSN_RS2(addr));
  357 +}
  358 +
335 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, 359 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
336 int arg1, tcg_target_long arg2) 360 int arg1, tcg_target_long arg2)
337 { 361 {
@@ -457,7 +481,7 @@ static const void * const qemu_st_helpers[4] = { @@ -457,7 +481,7 @@ static const void * const qemu_st_helpers[4] = {
457 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, 481 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
458 int opc) 482 int opc)
459 { 483 {
460 - int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op; 484 + int addr_reg, data_reg, r0, r1, mem_index, s_bits, ld_op;
461 #if defined(CONFIG_SOFTMMU) 485 #if defined(CONFIG_SOFTMMU)
462 uint8_t *label1_ptr, *label2_ptr; 486 uint8_t *label1_ptr, *label2_ptr;
463 #endif 487 #endif
@@ -565,11 +589,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -565,11 +589,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
565 r0 = addr_reg; 589 r0 = addr_reg;
566 #endif 590 #endif
567 591
568 -#ifdef TARGET_WORDS_BIGENDIAN  
569 - bswap = 0;  
570 -#else  
571 - bswap = 1;  
572 -#endif  
573 switch(opc) { 592 switch(opc) {
574 case 0: 593 case 0:
575 /* ldub [r0], data_reg */ 594 /* ldub [r0], data_reg */
@@ -580,39 +599,49 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -580,39 +599,49 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
580 tcg_out_ldst(s, data_reg, r0, 0, LDSB); 599 tcg_out_ldst(s, data_reg, r0, 0, LDSB);
581 break; 600 break;
582 case 1: 601 case 1:
  602 +#ifdef TARGET_WORDS_BIGENDIAN
583 /* lduh [r0], data_reg */ 603 /* lduh [r0], data_reg */
584 tcg_out_ldst(s, data_reg, r0, 0, LDUH); 604 tcg_out_ldst(s, data_reg, r0, 0, LDUH);
585 - if (bswap) {  
586 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
587 - } 605 +#else
  606 + /* lduha [r0] ASI_PRIMARY_LITTLE, data_reg */
  607 + tcg_out_ldst_asi(s, data_reg, r0, 0, LDUHA, ASI_PRIMARY_LITTLE);
  608 +#endif
588 break; 609 break;
589 case 1 | 4: 610 case 1 | 4:
  611 +#ifdef TARGET_WORDS_BIGENDIAN
590 /* ldsh [r0], data_reg */ 612 /* ldsh [r0], data_reg */
591 tcg_out_ldst(s, data_reg, r0, 0, LDSH); 613 tcg_out_ldst(s, data_reg, r0, 0, LDSH);
592 - if (bswap) {  
593 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
594 - } 614 +#else
  615 + /* ldsha [r0] ASI_PRIMARY_LITTLE, data_reg */
  616 + tcg_out_ldst_asi(s, data_reg, r0, 0, LDSHA, ASI_PRIMARY_LITTLE);
  617 +#endif
595 break; 618 break;
596 case 2: 619 case 2:
  620 +#ifdef TARGET_WORDS_BIGENDIAN
597 /* lduw [r0], data_reg */ 621 /* lduw [r0], data_reg */
598 tcg_out_ldst(s, data_reg, r0, 0, LDUW); 622 tcg_out_ldst(s, data_reg, r0, 0, LDUW);
599 - if (bswap) {  
600 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
601 - } 623 +#else
  624 + /* lduwa [r0] ASI_PRIMARY_LITTLE, data_reg */
  625 + tcg_out_ldst_asi(s, data_reg, r0, 0, LDUWA, ASI_PRIMARY_LITTLE);
  626 +#endif
602 break; 627 break;
603 case 2 | 4: 628 case 2 | 4:
  629 +#ifdef TARGET_WORDS_BIGENDIAN
604 /* ldsw [r0], data_reg */ 630 /* ldsw [r0], data_reg */
605 tcg_out_ldst(s, data_reg, r0, 0, LDSW); 631 tcg_out_ldst(s, data_reg, r0, 0, LDSW);
606 - if (bswap) {  
607 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
608 - } 632 +#else
  633 + /* ldswa [r0] ASI_PRIMARY_LITTLE, data_reg */
  634 + tcg_out_ldst_asi(s, data_reg, r0, 0, LDSWA, ASI_PRIMARY_LITTLE);
  635 +#endif
609 break; 636 break;
610 case 3: 637 case 3:
  638 +#ifdef TARGET_WORDS_BIGENDIAN
611 /* ldx [r0], data_reg */ 639 /* ldx [r0], data_reg */
612 tcg_out_ldst(s, data_reg, r0, 0, LDX); 640 tcg_out_ldst(s, data_reg, r0, 0, LDX);
613 - if (bswap) {  
614 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
615 - } 641 +#else
  642 + /* ldxa [r0] ASI_PRIMARY_LITTLE, data_reg */
  643 + tcg_out_ldst_asi(s, data_reg, r0, 0, LDXA, ASI_PRIMARY_LITTLE);
  644 +#endif
616 break; 645 break;
617 default: 646 default:
618 tcg_abort(); 647 tcg_abort();
@@ -629,7 +658,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -629,7 +658,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
629 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, 658 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
630 int opc) 659 int opc)
631 { 660 {
632 - int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op; 661 + int addr_reg, data_reg, r0, r1, mem_index, s_bits, ld_op;
633 #if defined(CONFIG_SOFTMMU) 662 #if defined(CONFIG_SOFTMMU)
634 uint8_t *label1_ptr, *label2_ptr; 663 uint8_t *label1_ptr, *label2_ptr;
635 #endif 664 #endif
@@ -737,36 +766,37 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -737,36 +766,37 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
737 r0 = addr_reg; 766 r0 = addr_reg;
738 #endif 767 #endif
739 768
740 -#ifdef TARGET_WORDS_BIGENDIAN  
741 - bswap = 0;  
742 -#else  
743 - bswap = 1;  
744 -#endif  
745 switch(opc) { 769 switch(opc) {
746 case 0: 770 case 0:
747 /* stb data_reg, [r0] */ 771 /* stb data_reg, [r0] */
748 tcg_out_ldst(s, data_reg, r0, 0, STB); 772 tcg_out_ldst(s, data_reg, r0, 0, STB);
749 break; 773 break;
750 case 1: 774 case 1:
751 - if (bswap) {  
752 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
753 - } 775 +#ifdef TARGET_WORDS_BIGENDIAN
754 /* sth data_reg, [r0] */ 776 /* sth data_reg, [r0] */
755 tcg_out_ldst(s, data_reg, r0, 0, STH); 777 tcg_out_ldst(s, data_reg, r0, 0, STH);
  778 +#else
  779 + /* stha data_reg, [r0] ASI_PRIMARY_LITTLE */
  780 + tcg_out_ldst_asi(s, data_reg, r0, 0, STHA, ASI_PRIMARY_LITTLE);
  781 +#endif
756 break; 782 break;
757 case 2: 783 case 2:
758 - if (bswap) {  
759 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
760 - } 784 +#ifdef TARGET_WORDS_BIGENDIAN
761 /* stw data_reg, [r0] */ 785 /* stw data_reg, [r0] */
762 tcg_out_ldst(s, data_reg, r0, 0, STW); 786 tcg_out_ldst(s, data_reg, r0, 0, STW);
  787 +#else
  788 + /* stwa data_reg, [r0] ASI_PRIMARY_LITTLE */
  789 + tcg_out_ldst_asi(s, data_reg, r0, 0, STWA, ASI_PRIMARY_LITTLE);
  790 +#endif
763 break; 791 break;
764 case 3: 792 case 3:
765 - if (bswap) {  
766 - fprintf(stderr, "unimplemented %s with bswap\n", __func__);  
767 - } 793 +#ifdef TARGET_WORDS_BIGENDIAN
768 /* stx data_reg, [r0] */ 794 /* stx data_reg, [r0] */
769 tcg_out_ldst(s, data_reg, r0, 0, STX); 795 tcg_out_ldst(s, data_reg, r0, 0, STX);
  796 +#else
  797 + /* stxa data_reg, [r0] ASI_PRIMARY_LITTLE */
  798 + tcg_out_ldst_asi(s, data_reg, r0, 0, STXA, ASI_PRIMARY_LITTLE);
  799 +#endif
770 break; 800 break;
771 default: 801 default:
772 tcg_abort(); 802 tcg_abort();