Commit 8384dd67fec5652a09ada4576214abfafab32c0c
1 parent
a8c768c0
Implement byte swapping accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4574 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
104 additions
and
36 deletions
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(); | ... | ... |