Revision be5a4eb7
b/tcg/i386/tcg-target.c | ||
---|---|---|
704 | 704 |
}; |
705 | 705 |
#endif |
706 | 706 |
|
707 |
#ifndef CONFIG_USER_ONLY |
|
708 |
#define GUEST_BASE 0 |
|
707 |
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, |
|
708 |
int base, tcg_target_long ofs, int sizeop) |
|
709 |
{ |
|
710 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
711 |
const int bswap = 1; |
|
712 |
#else |
|
713 |
const int bswap = 0; |
|
709 | 714 |
#endif |
715 |
switch (sizeop) { |
|
716 |
case 0: |
|
717 |
/* movzbl */ |
|
718 |
tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs); |
|
719 |
break; |
|
720 |
case 0 | 4: |
|
721 |
/* movsbl */ |
|
722 |
tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs); |
|
723 |
break; |
|
724 |
case 1: |
|
725 |
/* movzwl */ |
|
726 |
tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs); |
|
727 |
if (bswap) { |
|
728 |
tcg_out_rolw_8(s, datalo); |
|
729 |
} |
|
730 |
break; |
|
731 |
case 1 | 4: |
|
732 |
/* movswl */ |
|
733 |
tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs); |
|
734 |
if (bswap) { |
|
735 |
tcg_out_rolw_8(s, datalo); |
|
736 |
tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo); |
|
737 |
} |
|
738 |
break; |
|
739 |
case 2: |
|
740 |
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); |
|
741 |
if (bswap) { |
|
742 |
tcg_out_bswap32(s, datalo); |
|
743 |
} |
|
744 |
break; |
|
745 |
case 3: |
|
746 |
if (bswap) { |
|
747 |
int t = datalo; |
|
748 |
datalo = datahi; |
|
749 |
datahi = t; |
|
750 |
} |
|
751 |
if (base != datalo) { |
|
752 |
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); |
|
753 |
tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4); |
|
754 |
} else { |
|
755 |
tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4); |
|
756 |
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs); |
|
757 |
} |
|
758 |
if (bswap) { |
|
759 |
tcg_out_bswap32(s, datalo); |
|
760 |
tcg_out_bswap32(s, datahi); |
|
761 |
} |
|
762 |
break; |
|
763 |
default: |
|
764 |
tcg_abort(); |
|
765 |
} |
|
766 |
} |
|
710 | 767 |
|
711 | 768 |
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and |
712 | 769 |
EAX. It will be useful once fixed registers globals are less |
... | ... | |
714 | 771 |
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, |
715 | 772 |
int opc) |
716 | 773 |
{ |
717 |
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
|
|
774 |
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits; |
|
718 | 775 |
#if defined(CONFIG_SOFTMMU) |
719 | 776 |
uint8_t *label1_ptr, *label2_ptr; |
720 | 777 |
#endif |
... | ... | |
831 | 888 |
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1, |
832 | 889 |
offsetof(CPUTLBEntry, addend) - |
833 | 890 |
offsetof(CPUTLBEntry, addr_read)); |
891 |
|
|
892 |
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc); |
|
893 |
|
|
894 |
/* label2: */ |
|
895 |
*label2_ptr = s->code_ptr - label2_ptr - 1; |
|
834 | 896 |
#else |
835 |
r0 = addr_reg;
|
|
897 |
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
|
|
836 | 898 |
#endif |
899 |
} |
|
837 | 900 |
|
901 |
static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, |
|
902 |
int base, tcg_target_long ofs, int sizeop) |
|
903 |
{ |
|
838 | 904 |
#ifdef TARGET_WORDS_BIGENDIAN |
839 |
bswap = 1; |
|
905 |
const int bswap = 1;
|
|
840 | 906 |
#else |
841 |
bswap = 0; |
|
907 |
const int bswap = 0;
|
|
842 | 908 |
#endif |
843 |
switch(opc) { |
|
909 |
/* ??? Ideally we wouldn't need a scratch register. For user-only, |
|
910 |
we could perform the bswap twice to restore the original value |
|
911 |
instead of moving to the scratch. But as it is, the L constraint |
|
912 |
means that EDX is definitely free here. */ |
|
913 |
int scratch = TCG_REG_EDX; |
|
914 |
|
|
915 |
switch (sizeop) { |
|
844 | 916 |
case 0: |
845 |
/* movzbl */ |
|
846 |
tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE); |
|
847 |
break; |
|
848 |
case 0 | 4: |
|
849 |
/* movsbl */ |
|
850 |
tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE); |
|
917 |
tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs); |
|
851 | 918 |
break; |
852 | 919 |
case 1: |
853 |
/* movzwl */ |
|
854 |
tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE); |
|
855 |
if (bswap) { |
|
856 |
tcg_out_rolw_8(s, data_reg); |
|
857 |
} |
|
858 |
break; |
|
859 |
case 1 | 4: |
|
860 |
/* movswl */ |
|
861 |
tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE); |
|
862 | 920 |
if (bswap) { |
863 |
tcg_out_rolw_8(s, data_reg); |
|
864 |
|
|
865 |
/* movswl data_reg, data_reg */ |
|
866 |
tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg); |
|
921 |
tcg_out_mov(s, scratch, datalo); |
|
922 |
tcg_out_rolw_8(s, scratch); |
|
923 |
datalo = scratch; |
|
867 | 924 |
} |
925 |
/* movw */ |
|
926 |
tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16, |
|
927 |
datalo, base, ofs); |
|
868 | 928 |
break; |
869 | 929 |
case 2: |
870 |
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE); |
|
871 | 930 |
if (bswap) { |
872 |
tcg_out_bswap32(s, data_reg); |
|
931 |
tcg_out_mov(s, scratch, datalo); |
|
932 |
tcg_out_bswap32(s, scratch); |
|
933 |
datalo = scratch; |
|
873 | 934 |
} |
935 |
tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs); |
|
874 | 936 |
break; |
875 | 937 |
case 3: |
876 | 938 |
if (bswap) { |
877 |
int t = data_reg; |
|
878 |
data_reg = data_reg2; |
|
879 |
data_reg2 = t; |
|
880 |
} |
|
881 |
if (r0 != data_reg) { |
|
882 |
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE); |
|
883 |
tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4); |
|
939 |
tcg_out_mov(s, scratch, datahi); |
|
940 |
tcg_out_bswap32(s, scratch); |
|
941 |
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs); |
|
942 |
tcg_out_mov(s, scratch, datalo); |
|
943 |
tcg_out_bswap32(s, scratch); |
|
944 |
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4); |
|
884 | 945 |
} else { |
885 |
tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4); |
|
886 |
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE); |
|
887 |
} |
|
888 |
if (bswap) { |
|
889 |
tcg_out_bswap32(s, data_reg); |
|
890 |
tcg_out_bswap32(s, data_reg2); |
|
946 |
tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs); |
|
947 |
tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4); |
|
891 | 948 |
} |
892 | 949 |
break; |
893 | 950 |
default: |
894 | 951 |
tcg_abort(); |
895 | 952 |
} |
896 |
|
|
897 |
#if defined(CONFIG_SOFTMMU) |
|
898 |
/* label2: */ |
|
899 |
*label2_ptr = s->code_ptr - label2_ptr - 1; |
|
900 |
#endif |
|
901 | 953 |
} |
902 | 954 |
|
903 |
|
|
904 | 955 |
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, |
905 | 956 |
int opc) |
906 | 957 |
{ |
907 |
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
|
|
958 |
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits; |
|
908 | 959 |
#if defined(CONFIG_SOFTMMU) |
909 | 960 |
int stack_adjust; |
910 | 961 |
uint8_t *label1_ptr, *label2_ptr; |
... | ... | |
1041 | 1092 |
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1, |
1042 | 1093 |
offsetof(CPUTLBEntry, addend) - |
1043 | 1094 |
offsetof(CPUTLBEntry, addr_write)); |
1044 |
#else |
|
1045 |
r0 = addr_reg; |
|
1046 |
#endif |
|
1047 | 1095 |
|
1048 |
#ifdef TARGET_WORDS_BIGENDIAN |
|
1049 |
bswap = 1; |
|
1050 |
#else |
|
1051 |
bswap = 0; |
|
1052 |
#endif |
|
1053 |
switch(opc) { |
|
1054 |
case 0: |
|
1055 |
tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE); |
|
1056 |
break; |
|
1057 |
case 1: |
|
1058 |
if (bswap) { |
|
1059 |
tcg_out_mov(s, r1, data_reg); |
|
1060 |
tcg_out_rolw_8(s, r1); |
|
1061 |
data_reg = r1; |
|
1062 |
} |
|
1063 |
/* movw */ |
|
1064 |
tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16, |
|
1065 |
data_reg, r0, GUEST_BASE); |
|
1066 |
break; |
|
1067 |
case 2: |
|
1068 |
if (bswap) { |
|
1069 |
tcg_out_mov(s, r1, data_reg); |
|
1070 |
tcg_out_bswap32(s, r1); |
|
1071 |
data_reg = r1; |
|
1072 |
} |
|
1073 |
tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE); |
|
1074 |
break; |
|
1075 |
case 3: |
|
1076 |
if (bswap) { |
|
1077 |
tcg_out_mov(s, r1, data_reg2); |
|
1078 |
tcg_out_bswap32(s, r1); |
|
1079 |
tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE); |
|
1080 |
tcg_out_mov(s, r1, data_reg); |
|
1081 |
tcg_out_bswap32(s, r1); |
|
1082 |
tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4); |
|
1083 |
} else { |
|
1084 |
tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE); |
|
1085 |
tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4); |
|
1086 |
} |
|
1087 |
break; |
|
1088 |
default: |
|
1089 |
tcg_abort(); |
|
1090 |
} |
|
1096 |
tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc); |
|
1091 | 1097 |
|
1092 |
#if defined(CONFIG_SOFTMMU) |
|
1093 | 1098 |
/* label2: */ |
1094 | 1099 |
*label2_ptr = s->code_ptr - label2_ptr - 1; |
1100 |
#else |
|
1101 |
tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc); |
|
1095 | 1102 |
#endif |
1096 | 1103 |
} |
1097 | 1104 |
|
Also available in: Unified diff