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 233 int val;
234 234 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
235 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 245 #else
237 246 uint8_t *p = ptr;
238 247 return p[0] | (p[1] << 8);
... ... @@ -245,6 +254,11 @@ static inline int ldsw_le_p(void *ptr)
245 254 int val;
246 255 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
247 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 262 #else
249 263 uint8_t *p = ptr;
250 264 return (int16_t)(p[0] | (p[1] << 8));
... ... @@ -257,6 +271,11 @@ static inline int ldl_le_p(void *ptr)
257 271 int val;
258 272 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
259 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 279 #else
261 280 uint8_t *p = ptr;
262 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 284  
266 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 293 uint8_t *p = ptr;
269 294 uint32_t v1, v2;
270 295 v1 = ldl_le_p(p);
271 296 v2 = ldl_le_p(p + 4);
272 297 return v1 | ((uint64_t)v2 << 32);
  298 +#endif
273 299 }
274 300  
275 301 static inline void stw_le_p(void *ptr, int v)
276 302 {
277 303 #ifdef __powerpc__
278 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 308 #else
280 309 uint8_t *p = ptr;
281 310 p[0] = v;
... ... @@ -287,6 +316,9 @@ static inline void stl_le_p(void *ptr, int v)
287 316 {
288 317 #ifdef __powerpc__
289 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 322 #else
291 323 uint8_t *p = ptr;
292 324 p[0] = v;
... ... @@ -298,9 +330,15 @@ static inline void stl_le_p(void *ptr, int v)
298 330  
299 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 338 uint8_t *p = ptr;
302 339 stl_le_p(p, (uint32_t)v);
303 340 stl_le_p(p + 4, v >> 32);
  341 +#endif
304 342 }
305 343  
306 344 /* float access */
... ...
tcg/sparc/tcg-target.c
... ... @@ -178,6 +178,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
178 178 #define INSN_RD(x) ((x) << 25)
179 179 #define INSN_RS1(x) ((x) << 14)
180 180 #define INSN_RS2(x) (x)
  181 +#define INSN_ASI(x) ((x) << 5)
181 182  
182 183 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
183 184 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
... ... @@ -242,6 +243,21 @@ static inline int tcg_target_const_match(tcg_target_long val,
242 243 #define STH (INSN_OP(3) | INSN_OP3(0x06))
243 244 #define STW (INSN_OP(3) | INSN_OP3(0x04))
244 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 262 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
247 263 int op)
... ... @@ -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 359 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
336 360 int arg1, tcg_target_long arg2)
337 361 {
... ... @@ -457,7 +481,7 @@ static const void * const qemu_st_helpers[4] = {
457 481 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
458 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 485 #if defined(CONFIG_SOFTMMU)
462 486 uint8_t *label1_ptr, *label2_ptr;
463 487 #endif
... ... @@ -565,11 +589,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
565 589 r0 = addr_reg;
566 590 #endif
567 591  
568   -#ifdef TARGET_WORDS_BIGENDIAN
569   - bswap = 0;
570   -#else
571   - bswap = 1;
572   -#endif
573 592 switch(opc) {
574 593 case 0:
575 594 /* ldub [r0], data_reg */
... ... @@ -580,39 +599,49 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
580 599 tcg_out_ldst(s, data_reg, r0, 0, LDSB);
581 600 break;
582 601 case 1:
  602 +#ifdef TARGET_WORDS_BIGENDIAN
583 603 /* lduh [r0], data_reg */
584 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 609 break;
589 610 case 1 | 4:
  611 +#ifdef TARGET_WORDS_BIGENDIAN
590 612 /* ldsh [r0], data_reg */
591 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 618 break;
596 619 case 2:
  620 +#ifdef TARGET_WORDS_BIGENDIAN
597 621 /* lduw [r0], data_reg */
598 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 627 break;
603 628 case 2 | 4:
  629 +#ifdef TARGET_WORDS_BIGENDIAN
604 630 /* ldsw [r0], data_reg */
605 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 636 break;
610 637 case 3:
  638 +#ifdef TARGET_WORDS_BIGENDIAN
611 639 /* ldx [r0], data_reg */
612 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 645 break;
617 646 default:
618 647 tcg_abort();
... ... @@ -629,7 +658,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
629 658 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
630 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 662 #if defined(CONFIG_SOFTMMU)
634 663 uint8_t *label1_ptr, *label2_ptr;
635 664 #endif
... ... @@ -737,36 +766,37 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
737 766 r0 = addr_reg;
738 767 #endif
739 768  
740   -#ifdef TARGET_WORDS_BIGENDIAN
741   - bswap = 0;
742   -#else
743   - bswap = 1;
744   -#endif
745 769 switch(opc) {
746 770 case 0:
747 771 /* stb data_reg, [r0] */
748 772 tcg_out_ldst(s, data_reg, r0, 0, STB);
749 773 break;
750 774 case 1:
751   - if (bswap) {
752   - fprintf(stderr, "unimplemented %s with bswap\n", __func__);
753   - }
  775 +#ifdef TARGET_WORDS_BIGENDIAN
754 776 /* sth data_reg, [r0] */
755 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 782 break;
757 783 case 2:
758   - if (bswap) {
759   - fprintf(stderr, "unimplemented %s with bswap\n", __func__);
760   - }
  784 +#ifdef TARGET_WORDS_BIGENDIAN
761 785 /* stw data_reg, [r0] */
762 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 791 break;
764 792 case 3:
765   - if (bswap) {
766   - fprintf(stderr, "unimplemented %s with bswap\n", __func__);
767   - }
  793 +#ifdef TARGET_WORDS_BIGENDIAN
768 794 /* stx data_reg, [r0] */
769 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 800 break;
771 801 default:
772 802 tcg_abort();
... ...