]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
fix: handle ARM64 JIT MOVEM predec base
authorDimitris Panokostas <midwan@gmail.com>
Mon, 1 Jun 2026 17:06:40 +0000 (19:06 +0200)
committerDimitris Panokostas <midwan@gmail.com>
Mon, 1 Jun 2026 17:21:56 +0000 (19:21 +0200)
jit/arm/compemu_arm.cpp
jit/arm/gencomp_arm.c

index 541f54c28a7f15910644ad4071b867b0414d9505..72de3359f17e78df0ab89bbc9f0e66615967ea39 100644 (file)
@@ -11581,7 +11581,7 @@ uae_u32 REGPARAM2 op_48a0_0_comp_ff(uae_u32 opcode) {
        int i;
        signed char offset = 0;
        int srca = dstreg + 8;
-       if (!special_mem) {
+       if (!special_mem && !(mask & (1 << (7 - dstreg)))) {
                int native = alloc_scratch();
                get_n_addr(srca, native);
                for (i = 0; i < 16; i++) {
@@ -11592,10 +11592,15 @@ uae_u32 REGPARAM2 op_48a0_0_comp_ff(uae_u32 opcode) {
                }
                lea_l_brr(8 + dstreg, srca, (uae_s32) offset);
        } else {
+               int base = alloc_scratch();
+               lea_l_brr(base, srca, -2);
                for (i = 0; i < 16; i++) {
                        if ((mask >> i) & 1) {
+                               int value = 15 - i;
                                arm_SUB_l_ri8(srca, 2);
-                               writeword(srca, 15 - i);
+                               if (value == srca)
+                                       value = base;
+                               writeword(srca, value);
                        }
                }
                mov_l_rr(8 + dstreg, srca);
@@ -11788,7 +11793,7 @@ uae_u32 REGPARAM2 op_48e0_0_comp_ff(uae_u32 opcode) {
        int i;
        signed char offset = 0;
        int srca = dstreg + 8;
-       if (!special_mem) {
+       if (!special_mem && !(mask & (1 << (7 - dstreg)))) {
                int native = alloc_scratch();
                get_n_addr(srca, native);
                for (i = 0; i < 16; i++) {
@@ -11799,10 +11804,15 @@ uae_u32 REGPARAM2 op_48e0_0_comp_ff(uae_u32 opcode) {
                }
                lea_l_brr(8 + dstreg, srca, (uae_s32) offset);
        } else {
+               int base = alloc_scratch();
+               lea_l_brr(base, srca, -4);
                for (i = 0; i < 16; i++) {
                        if ((mask >> i) & 1) {
+                               int value = 15 - i;
                                arm_SUB_l_ri8(srca, 4);
-                               writelong(srca, 15 - i);
+                               if (value == srca)
+                                       value = base;
+                               writelong(srca, value);
                        }
                }
                mov_l_rr(8 + dstreg, srca);
@@ -38767,7 +38777,7 @@ uae_u32 REGPARAM2 op_48a0_0_comp_nf(uae_u32 opcode) {
        int i;
        signed char offset = 0;
        int srca = dstreg + 8;
-       if (!special_mem) {
+       if (!special_mem && !(mask & (1 << (7 - dstreg)))) {
                int native = alloc_scratch();
                get_n_addr(srca, native);
                for (i = 0; i < 16; i++) {
@@ -38778,10 +38788,15 @@ uae_u32 REGPARAM2 op_48a0_0_comp_nf(uae_u32 opcode) {
                }
                lea_l_brr(8 + dstreg, srca, (uae_s32) offset);
        } else {
+               int base = alloc_scratch();
+               lea_l_brr(base, srca, -2);
                for (i = 0; i < 16; i++) {
                        if ((mask >> i) & 1) {
+                               int value = 15 - i;
                                arm_SUB_l_ri8(srca, 2);
-                               writeword(srca, 15 - i);
+                               if (value == srca)
+                                       value = base;
+                               writeword(srca, value);
                        }
                }
                mov_l_rr(8 + dstreg, srca);
@@ -38973,7 +38988,7 @@ uae_u32 REGPARAM2 op_48e0_0_comp_nf(uae_u32 opcode) {
        int i;
        signed char offset = 0;
        int srca = dstreg + 8;
-       if (!special_mem) {
+       if (!special_mem && !(mask & (1 << (7 - dstreg)))) {
                int native = alloc_scratch();
                get_n_addr(srca, native);
                for (i = 0; i < 16; i++) {
@@ -38984,10 +38999,15 @@ uae_u32 REGPARAM2 op_48e0_0_comp_nf(uae_u32 opcode) {
                }
                lea_l_brr(8 + dstreg, srca, (uae_s32) offset);
        } else {
+               int base = alloc_scratch();
+               lea_l_brr(base, srca, -4);
                for (i = 0; i < 16; i++) {
                        if ((mask >> i) & 1) {
+                               int value = 15 - i;
                                arm_SUB_l_ri8(srca, 4);
-                               writelong(srca, 15 - i);
+                               if (value == srca)
+                                       value = base;
+                               writelong(srca, value);
                        }
                }
                mov_l_rr(8 + dstreg, srca);
index 90ef1374ba381c40844e8f11732fa2d096410c07..4352691481aa9aec0a35af42bb54a9f6a2f0e4af 100644 (file)
@@ -741,55 +741,97 @@ static void genmovemle(uae_u16 opcode) {
        genamode(table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2,
                        1);
 
-       comprintf("\tget_n_addr(srca,native,scratchie);\n");
-
-       if (table68k[opcode].dmode != Apdi) {
-               comprintf("\tfor (i=0;i<16;i++) {\n"
-                               "\t\tif ((mask>>i)&1) {\n");
+       if (table68k[opcode].dmode == Apdi) {
+               comprintf("\tif (!special_mem && !(mask & (1 << (7 - dstreg)))) {\n");
+               comprintf("\t\tget_n_addr(srca,native,scratchie);\n");
+               comprintf("\t\tfor (i=0;i<16;i++) {\n"
+                               "\t\t\tif ((mask>>i)&1) {\n");
+               switch (table68k[opcode].size) {
+               case sz_long:
+                       comprintf("\t\t\t\toffset-=4;\n"
+                                       "\t\t\t\tmov_l_rr(tmp,15-i);\n"
+                                       "\t\t\t\tmid_bswap_32(tmp);\n"
+                                       "\t\t\t\tmov_l_Rr(native,tmp,offset);\n");
+                       break;
+               case sz_word:
+                       comprintf("\t\t\t\toffset-=2;\n"
+                                       "\t\t\t\tmov_l_rr(tmp,15-i);\n"
+                                       "\t\t\t\tmid_bswap_16(tmp);\n"
+                                       "\t\t\t\tmov_w_Rr(native,tmp,offset);\n");
+                       break;
+               default:
+                       assert(0);
+                       break;
+               }
+               comprintf("\t\t\t}\n"
+                               "\t\t}\n");
+               comprintf("\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n");
+               comprintf("\t} else {\n");
                switch (table68k[opcode].size) {
                case sz_long:
-                       comprintf("\t\t\tmov_l_rr(tmp,i);\n"
-                                       "\t\t\tmid_bswap_32(tmp);\n"
-                                       "\t\t\tmov_l_Rr(native,tmp,offset);\n"
-                                       "\t\t\toffset+=4;\n");
+                       comprintf("\t\tint base=scratchie++;\n"
+                                       "\t\tlea_l_brr(base,srca,-4);\n");
                        break;
                case sz_word:
-                       comprintf("\t\t\tmov_l_rr(tmp,i);\n"
-                                       "\t\t\tmid_bswap_16(tmp);\n"
-                                       "\t\t\tmov_w_Rr(native,tmp,offset);\n"
-                                       "\t\t\toffset+=2;\n");
+                       comprintf("\t\tint base=scratchie++;\n"
+                                       "\t\tlea_l_brr(base,srca,-2);\n");
                        break;
                default:
                        assert(0);
                        break;
                }
-       } else { /* Pre-decrement */
-               comprintf("\tfor (i=0;i<16;i++) {\n"
-                               "\t\tif ((mask>>i)&1) {\n");
+               comprintf("\t\tfor (i=0;i<16;i++) {\n"
+                               "\t\t\tif ((mask>>i)&1) {\n");
                switch (table68k[opcode].size) {
                case sz_long:
-                       comprintf("\t\t\toffset-=4;\n"
-                                       "\t\t\tmov_l_rr(tmp,15-i);\n"
-                                       "\t\t\tmid_bswap_32(tmp);\n"
-                                       "\t\t\tmov_l_Rr(native,tmp,offset);\n");
+                       comprintf("\t\t\t\tint value=15-i;\n"
+                                       "\t\t\t\tsub_l_ri(srca,4);\n"
+                                       "\t\t\t\tif (value == srca)\n"
+                                       "\t\t\t\t\tvalue=base;\n"
+                                       "\t\t\t\twritelong(srca,value);\n");
                        break;
                case sz_word:
-                       comprintf("\t\t\toffset-=2;\n"
-                                       "\t\t\tmov_l_rr(tmp,15-i);\n"
-                                       "\t\t\tmid_bswap_16(tmp);\n"
-                                       "\t\t\tmov_w_Rr(native,tmp,offset);\n");
+                       comprintf("\t\t\t\tint value=15-i;\n"
+                                       "\t\t\t\tsub_l_ri(srca,2);\n"
+                                       "\t\t\t\tif (value == srca)\n"
+                                       "\t\t\t\t\tvalue=base;\n"
+                                       "\t\t\t\twriteword(srca,value);\n");
                        break;
                default:
                        assert(0);
                        break;
                }
+               comprintf("\t\t\t}\n"
+                               "\t\t}\n");
+               comprintf("\t\tmov_l_rr(8+dstreg,srca);\n");
+               comprintf("\t}\n");
+               return;
+       }
+
+       comprintf("\tget_n_addr(srca,native,scratchie);\n");
+
+       comprintf("\tfor (i=0;i<16;i++) {\n"
+                       "\t\tif ((mask>>i)&1) {\n");
+       switch (table68k[opcode].size) {
+       case sz_long:
+               comprintf("\t\t\tmov_l_rr(tmp,i);\n"
+                               "\t\t\tmid_bswap_32(tmp);\n"
+                               "\t\t\tmov_l_Rr(native,tmp,offset);\n"
+                               "\t\t\toffset+=4;\n");
+               break;
+       case sz_word:
+               comprintf("\t\t\tmov_l_rr(tmp,i);\n"
+                               "\t\t\tmid_bswap_16(tmp);\n"
+                               "\t\t\tmov_w_Rr(native,tmp,offset);\n"
+                               "\t\t\toffset+=2;\n");
+               break;
+       default:
+               assert(0);
+               break;
        }
 
        comprintf("\t\t}\n"
                        "\t}");
-       if (table68k[opcode].dmode == Apdi) {
-               comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n");
-       }
 }
 
 static void duplicate_carry(void) {