159 |
|
return (prop[opcode].cflow == fl_const_jump); |
160 |
|
} |
161 |
|
|
162 |
+ |
static inline bool may_trap(uae_u32 opcode) |
163 |
+ |
{ |
164 |
+ |
return (prop[opcode].cflow & fl_trap); |
165 |
+ |
} |
166 |
+ |
|
167 |
+ |
static inline unsigned int cft_map (unsigned int f) |
168 |
+ |
{ |
169 |
+ |
#ifndef HAVE_GET_WORD_UNSWAPPED |
170 |
+ |
return f; |
171 |
+ |
#else |
172 |
+ |
return ((f >> 8) & 255) | ((f & 255) << 8); |
173 |
+ |
#endif |
174 |
+ |
} |
175 |
+ |
|
176 |
|
uae_u8* start_pc_p; |
177 |
|
uae_u32 start_pc; |
178 |
|
uae_u32 current_block_pc_p; |
200 |
|
static void* popall_recompile_block=NULL; |
201 |
|
static void* popall_check_checksum=NULL; |
202 |
|
|
189 |
– |
extern uae_u32 oink; |
190 |
– |
extern unsigned long foink3; |
191 |
– |
extern unsigned long foink; |
192 |
– |
|
203 |
|
/* The 68k only ever executes from even addresses. So right now, we |
204 |
|
* waste half the entries in this array |
205 |
|
* UPDATE: We now use those entries to store the start of the linked |
812 |
|
int touchcnt; |
813 |
|
|
814 |
|
/******************************************************************** |
815 |
+ |
* Partial register flushing for optimized calls * |
816 |
+ |
********************************************************************/ |
817 |
+ |
|
818 |
+ |
struct regusage { |
819 |
+ |
uae_u16 rmask; |
820 |
+ |
uae_u16 wmask; |
821 |
+ |
}; |
822 |
+ |
|
823 |
+ |
static inline void ru_set(uae_u16 *mask, int reg) |
824 |
+ |
{ |
825 |
+ |
#if USE_OPTIMIZED_CALLS |
826 |
+ |
*mask |= 1 << reg; |
827 |
+ |
#endif |
828 |
+ |
} |
829 |
+ |
|
830 |
+ |
static inline bool ru_get(const uae_u16 *mask, int reg) |
831 |
+ |
{ |
832 |
+ |
#if USE_OPTIMIZED_CALLS |
833 |
+ |
return (*mask & (1 << reg)); |
834 |
+ |
#else |
835 |
+ |
/* Default: instruction reads & write to register */ |
836 |
+ |
return true; |
837 |
+ |
#endif |
838 |
+ |
} |
839 |
+ |
|
840 |
+ |
static inline void ru_set_read(regusage *ru, int reg) |
841 |
+ |
{ |
842 |
+ |
ru_set(&ru->rmask, reg); |
843 |
+ |
} |
844 |
+ |
|
845 |
+ |
static inline void ru_set_write(regusage *ru, int reg) |
846 |
+ |
{ |
847 |
+ |
ru_set(&ru->wmask, reg); |
848 |
+ |
} |
849 |
+ |
|
850 |
+ |
static inline bool ru_read_p(const regusage *ru, int reg) |
851 |
+ |
{ |
852 |
+ |
return ru_get(&ru->rmask, reg); |
853 |
+ |
} |
854 |
+ |
|
855 |
+ |
static inline bool ru_write_p(const regusage *ru, int reg) |
856 |
+ |
{ |
857 |
+ |
return ru_get(&ru->wmask, reg); |
858 |
+ |
} |
859 |
+ |
|
860 |
+ |
static void ru_fill_ea(regusage *ru, int reg, amodes mode, |
861 |
+ |
wordsizes size, int write_mode) |
862 |
+ |
{ |
863 |
+ |
switch (mode) { |
864 |
+ |
case Areg: |
865 |
+ |
reg += 8; |
866 |
+ |
/* fall through */ |
867 |
+ |
case Dreg: |
868 |
+ |
ru_set(write_mode ? &ru->wmask : &ru->rmask, reg); |
869 |
+ |
break; |
870 |
+ |
case Ad16: |
871 |
+ |
/* skip displacment */ |
872 |
+ |
m68k_pc_offset += 2; |
873 |
+ |
case Aind: |
874 |
+ |
case Aipi: |
875 |
+ |
case Apdi: |
876 |
+ |
ru_set_read(ru, reg+8); |
877 |
+ |
break; |
878 |
+ |
case Ad8r: |
879 |
+ |
ru_set_read(ru, reg+8); |
880 |
+ |
/* fall through */ |
881 |
+ |
case PC8r: { |
882 |
+ |
uae_u16 dp = comp_get_iword((m68k_pc_offset+=2)-2); |
883 |
+ |
reg = (dp >> 12) & 15; |
884 |
+ |
ru_set_read(ru, reg); |
885 |
+ |
if (dp & 0x100) |
886 |
+ |
m68k_pc_offset += (((dp & 0x30) >> 3) & 7) + ((dp & 3) * 2); |
887 |
+ |
break; |
888 |
+ |
} |
889 |
+ |
case PC16: |
890 |
+ |
case absw: |
891 |
+ |
case imm0: |
892 |
+ |
case imm1: |
893 |
+ |
m68k_pc_offset += 2; |
894 |
+ |
break; |
895 |
+ |
case absl: |
896 |
+ |
case imm2: |
897 |
+ |
m68k_pc_offset += 4; |
898 |
+ |
break; |
899 |
+ |
case immi: |
900 |
+ |
m68k_pc_offset += (size == sz_long) ? 4 : 2; |
901 |
+ |
break; |
902 |
+ |
} |
903 |
+ |
} |
904 |
+ |
|
905 |
+ |
/* TODO: split into a static initialization part and a dynamic one |
906 |
+ |
(instructions depending on extension words) */ |
907 |
+ |
static void ru_fill(regusage *ru, uae_u32 opcode) |
908 |
+ |
{ |
909 |
+ |
m68k_pc_offset += 2; |
910 |
+ |
|
911 |
+ |
/* Default: no register is used or written to */ |
912 |
+ |
ru->rmask = 0; |
913 |
+ |
ru->wmask = 0; |
914 |
+ |
|
915 |
+ |
uae_u32 real_opcode = cft_map(opcode); |
916 |
+ |
struct instr *dp = &table68k[real_opcode]; |
917 |
+ |
|
918 |
+ |
bool rw_dest = true; |
919 |
+ |
bool handled = false; |
920 |
+ |
|
921 |
+ |
/* Handle some instructions specifically */ |
922 |
+ |
uae_u16 reg, ext; |
923 |
+ |
switch (dp->mnemo) { |
924 |
+ |
case i_BFCHG: |
925 |
+ |
case i_BFCLR: |
926 |
+ |
case i_BFEXTS: |
927 |
+ |
case i_BFEXTU: |
928 |
+ |
case i_BFFFO: |
929 |
+ |
case i_BFINS: |
930 |
+ |
case i_BFSET: |
931 |
+ |
case i_BFTST: |
932 |
+ |
ext = comp_get_iword((m68k_pc_offset+=2)-2); |
933 |
+ |
if (ext & 0x800) ru_set_read(ru, (ext >> 6) & 7); |
934 |
+ |
if (ext & 0x020) ru_set_read(ru, ext & 7); |
935 |
+ |
ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); |
936 |
+ |
if (dp->dmode == Dreg) |
937 |
+ |
ru_set_read(ru, dp->dreg); |
938 |
+ |
switch (dp->mnemo) { |
939 |
+ |
case i_BFEXTS: |
940 |
+ |
case i_BFEXTU: |
941 |
+ |
case i_BFFFO: |
942 |
+ |
ru_set_write(ru, (ext >> 12) & 7); |
943 |
+ |
break; |
944 |
+ |
case i_BFINS: |
945 |
+ |
ru_set_read(ru, (ext >> 12) & 7); |
946 |
+ |
/* fall through */ |
947 |
+ |
case i_BFCHG: |
948 |
+ |
case i_BFCLR: |
949 |
+ |
case i_BSET: |
950 |
+ |
if (dp->dmode == Dreg) |
951 |
+ |
ru_set_write(ru, dp->dreg); |
952 |
+ |
break; |
953 |
+ |
} |
954 |
+ |
handled = true; |
955 |
+ |
rw_dest = false; |
956 |
+ |
break; |
957 |
+ |
|
958 |
+ |
case i_BTST: |
959 |
+ |
rw_dest = false; |
960 |
+ |
break; |
961 |
+ |
|
962 |
+ |
case i_CAS: |
963 |
+ |
{ |
964 |
+ |
ext = comp_get_iword((m68k_pc_offset+=2)-2); |
965 |
+ |
int Du = ext & 7; |
966 |
+ |
ru_set_read(ru, Du); |
967 |
+ |
int Dc = (ext >> 6) & 7; |
968 |
+ |
ru_set_read(ru, Dc); |
969 |
+ |
ru_set_write(ru, Dc); |
970 |
+ |
break; |
971 |
+ |
} |
972 |
+ |
case i_CAS2: |
973 |
+ |
{ |
974 |
+ |
int Dc1, Dc2, Du1, Du2, Rn1, Rn2; |
975 |
+ |
ext = comp_get_iword((m68k_pc_offset+=2)-2); |
976 |
+ |
Rn1 = (ext >> 12) & 15; |
977 |
+ |
Du1 = (ext >> 6) & 7; |
978 |
+ |
Dc1 = ext & 7; |
979 |
+ |
ru_set_read(ru, Rn1); |
980 |
+ |
ru_set_read(ru, Du1); |
981 |
+ |
ru_set_read(ru, Dc1); |
982 |
+ |
ru_set_write(ru, Dc1); |
983 |
+ |
ext = comp_get_iword((m68k_pc_offset+=2)-2); |
984 |
+ |
Rn2 = (ext >> 12) & 15; |
985 |
+ |
Du2 = (ext >> 6) & 7; |
986 |
+ |
Dc2 = ext & 7; |
987 |
+ |
ru_set_read(ru, Rn2); |
988 |
+ |
ru_set_read(ru, Du2); |
989 |
+ |
ru_set_write(ru, Dc2); |
990 |
+ |
break; |
991 |
+ |
} |
992 |
+ |
case i_DIVL: case i_MULL: |
993 |
+ |
m68k_pc_offset += 2; |
994 |
+ |
break; |
995 |
+ |
case i_LEA: |
996 |
+ |
case i_MOVE: case i_MOVEA: case i_MOVE16: |
997 |
+ |
rw_dest = false; |
998 |
+ |
break; |
999 |
+ |
case i_PACK: case i_UNPK: |
1000 |
+ |
rw_dest = false; |
1001 |
+ |
m68k_pc_offset += 2; |
1002 |
+ |
break; |
1003 |
+ |
case i_TRAPcc: |
1004 |
+ |
m68k_pc_offset += (dp->size == sz_long) ? 4 : 2; |
1005 |
+ |
break; |
1006 |
+ |
case i_RTR: |
1007 |
+ |
/* do nothing, just for coverage debugging */ |
1008 |
+ |
break; |
1009 |
+ |
/* TODO: handle EXG instruction */ |
1010 |
+ |
} |
1011 |
+ |
|
1012 |
+ |
/* Handle A-Traps better */ |
1013 |
+ |
if ((real_opcode & 0xf000) == 0xa000) { |
1014 |
+ |
handled = true; |
1015 |
+ |
} |
1016 |
+ |
|
1017 |
+ |
/* Handle EmulOps better */ |
1018 |
+ |
if ((real_opcode & 0xff00) == 0x7100) { |
1019 |
+ |
handled = true; |
1020 |
+ |
ru->rmask = 0xffff; |
1021 |
+ |
ru->wmask = 0; |
1022 |
+ |
} |
1023 |
+ |
|
1024 |
+ |
if (dp->suse && !handled) |
1025 |
+ |
ru_fill_ea(ru, dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); |
1026 |
+ |
|
1027 |
+ |
if (dp->duse && !handled) |
1028 |
+ |
ru_fill_ea(ru, dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 1); |
1029 |
+ |
|
1030 |
+ |
if (rw_dest) |
1031 |
+ |
ru->rmask |= ru->wmask; |
1032 |
+ |
|
1033 |
+ |
handled = handled || dp->suse || dp->duse; |
1034 |
+ |
|
1035 |
+ |
/* Mark all registers as used/written if the instruction may trap */ |
1036 |
+ |
if (may_trap(opcode)) { |
1037 |
+ |
handled = true; |
1038 |
+ |
ru->rmask = 0xffff; |
1039 |
+ |
ru->wmask = 0xffff; |
1040 |
+ |
} |
1041 |
+ |
|
1042 |
+ |
if (!handled) { |
1043 |
+ |
write_log("ru_fill: %04x = { %04x, %04x }\n", |
1044 |
+ |
real_opcode, ru->rmask, ru->wmask); |
1045 |
+ |
abort(); |
1046 |
+ |
} |
1047 |
+ |
} |
1048 |
+ |
|
1049 |
+ |
/******************************************************************** |
1050 |
|
* register allocation per block logging * |
1051 |
|
********************************************************************/ |
1052 |
|
|
4877 |
|
return b ? "on" : "off"; |
4878 |
|
} |
4879 |
|
|
4635 |
– |
static __inline__ unsigned int cft_map (unsigned int f) |
4636 |
– |
{ |
4637 |
– |
#ifndef HAVE_GET_WORD_UNSWAPPED |
4638 |
– |
return f; |
4639 |
– |
#else |
4640 |
– |
return ((f >> 8) & 255) | ((f & 255) << 8); |
4641 |
– |
#endif |
4642 |
– |
} |
4643 |
– |
|
4880 |
|
void compiler_init(void) |
4881 |
|
{ |
4882 |
|
static bool initialized = false; |
6456 |
|
comp_pc_p=(uae_u8*)pc_hist[i].location; |
6457 |
|
init_comp(); |
6458 |
|
} |
6459 |
< |
was_comp++; |
6459 |
> |
was_comp=1; |
6460 |
|
|
6461 |
|
comptbl[opcode](opcode); |
6462 |
|
freescratch(); |
6488 |
|
// raw_cputbl_count[] is indexed with plain opcode (in m68k order) |
6489 |
|
raw_add_l_mi((uae_u32)&raw_cputbl_count[cft_map(opcode)],1); |
6490 |
|
#endif |
6255 |
– |
//raw_add_l_mi((uae_u32)&oink,1); // FIXME |
6491 |
|
#if USE_NORMAL_CALLING_CONVENTION |
6492 |
|
raw_inc_sp(4); |
6493 |
|
#endif |
6259 |
– |
if (needed_flags) { |
6260 |
– |
//raw_mov_l_mi((uae_u32)&foink3,(uae_u32)opcode+65536); |
6261 |
– |
} |
6262 |
– |
else { |
6263 |
– |
//raw_mov_l_mi((uae_u32)&foink3,(uae_u32)opcode); |
6264 |
– |
} |
6494 |
|
|
6495 |
|
if (i < blocklen - 1) { |
6496 |
|
uae_s8* branchadd; |