fix compatibility with ancient gas
[cyclone68000.git] / Ea.cpp
diff --git a/Ea.cpp b/Ea.cpp
index 606e8f4..5969529 100644 (file)
--- a/Ea.cpp
+++ b/Ea.cpp
@@ -138,7 +138,7 @@ static int EaCalcReg(int r,int ea,int mask,int forceor,int shift,int noshift=0)
 // If ea>=0x10, trashes r0,r2 and r3, else nothing\r
 // size values 0, 1, 2 ~ byte, word, long\r
 // mask shows usable bits in r8\r
-int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)\r
+int EaCalc(int a,int mask,int ea,int size,EaRWType type)\r
 {\r
   char text[32]="";\r
 \r
@@ -146,8 +146,9 @@ int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
 \r
   if (ea<0x10)\r
   {\r
+    // Saves one opcode as we can shift in ldr/str\r
     int noshift=0;\r
-    if (size>=2||(size==0&&(top||!sign_extend))) noshift=1; // Saves one opcode\r
+    if (size >= 2 || (size == 0 && type != earwt_sign_extend)) noshift=1;\r
 \r
     ot(";@ EaCalc : Get register index into r%d:\n",a);\r
 \r
@@ -255,8 +256,7 @@ int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
     ot("  ldr r0,[r7,#0x60] ;@ Get Memory base\n");\r
     ot("  sub r0,r4,r0 ;@ Real PC\n");\r
     ot("  ldrsh r2,[r4],#2 ;@ Fetch extension\n"); pc_dirty=1;\r
-    ot("  mov r0,r0,lsl #8\n");\r
-    ot("  add r%d,r2,r0,asr #8 ;@ ($nn,PC)\n",a);\r
+    ot("  add r%d,r2,r0 ;@ ($nn,PC)\n",a);\r
     Cycles+=size<2 ? 8:12; // Extra cycles\r
     return 0;\r
   }\r
@@ -267,7 +267,6 @@ int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
     ot("  ldrh r3,[r4] ;@ Get extension word\n");\r
     ot("  sub r0,r4,r0 ;@ r0=PC\n");\r
     ot("  add r4,r4,#2\n"); pc_dirty=1;\r
-    ot("  mov r0,r0,asl #8 ;@ use only 24bits of PC\n");\r
     ot("  mov r2,r3,lsr #10\n");\r
     ot("  tst r3,#0x0800 ;@ Is Rn Word or Long\n");\r
     ot("  and r2,r2,#0x3c ;@ r2=Index of Rn\n");\r
@@ -275,7 +274,7 @@ int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
     ot("  ldrne   r2,[r7,r2] ;@ r2=Rn.l\n");\r
     ot("  mov r3,r3,asl #24 ;@ r3=Get 8-bit signed Disp\n");\r
     ot("  add r2,r2,r3,asr #24 ;@ r2=Disp+Rn\n");\r
-    ot("  add r%d,r2,r0,asr #8 ;@ r%d=Disp+PC+Rn\n",a,a);\r
+    ot("  add r%d,r2,r0 ;@ r%d=Disp+PC+Rn\n",a,a);\r
     Cycles+=size<2 ? 10:14; // Extra cycles\r
     return 0;\r
   }\r
@@ -302,16 +301,22 @@ int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend)
 // ---------------------------------------------------------------------------\r
 // Read effective address in (ARM Register 'a') to ARM register 'v'\r
 // 'a' and 'v' can be anything but 0 is generally best (for both)\r
-// If (ea<0x10) nothing is trashed, else r0-r3 is trashed\r
-// If 'top' is given, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000\r
-// If top is 0 and sign_extend is not, then ARM register v is sign extended,\r
-// e.g. 0xc000 -> 0xffffc000 (else it may or may not be sign extended)\r
-\r
-int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)\r
+// If (ea<0x10) nothing is trashed, else r0-r3,r12 is trashed\r
+int EaRead(int a,int v,int ea,int size,int mask,EaRWType type,int set_nz)\r
 {\r
   char text[32]="";\r
+  const char *s="";\r
+  int flags_set=0;\r
   int shift=0;\r
 \r
+  if (set_nz) {\r
+    if (type == earwt_msb_dont_care || type == earwt_zero_extend) {\r
+      fprintf(stderr, "set_nz on msb_dont_care/zero_extend?\n");\r
+      exit(1);\r
+    }\r
+    s="s";\r
+  }\r
+\r
   shift=32-(8<<size);\r
 \r
   DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
@@ -319,21 +324,26 @@ int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)
   if (ea<0x10)\r
   {\r
     int lsl=0,low=0,nsarm=size&3,i;\r
-    if (size>=2||(size==0&&(top||!sign_extend))) {\r
-      if(mask)\r
+    if (size >= 2 || (size == 0 && type != earwt_sign_extend)) {\r
+      if (mask)\r
         for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
       lsl=2-low; // Having a lsl #2 here saves one opcode\r
     }\r
 \r
-    if (top||!sign_extend) nsarm=3;\r
+    if (type == earwt_shifted_up || type == earwt_msb_dont_care)\r
+      // use plain ldr\r
+      nsarm = 3;\r
 \r
     ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v);\r
 \r
     if      (lsl>0) ot("  ldr%s r%d,[r7,r%d,lsl #%i]\n",Narm[nsarm],v,a,lsl);\r
     else if (lsl<0) ot("  ldr%s r%d,[r7,r%d,lsr #%i]\n",Narm[nsarm],v,a,-lsl);\r
-    else            ot("  ldr%s r%d,[r7,r%d]\n",Sarm[nsarm],v,a);\r
+    else            ot("  ldr%s r%d,[r7,r%d]\n",type==earwt_sign_extend?Sarm[nsarm]:Narm[nsarm],v,a);\r
 \r
-    if (top&&shift) ot("  mov r%d,r%d,asl #%d\n",v,v,shift);\r
+    if (type == earwt_shifted_up && shift)\r
+      ot("  mov%s r%d,r%d,asl #%d\n",s,v,v,shift);\r
+    else if (set_nz)\r
+      ot("  tst r%d,r%d\n",v,v);\r
 \r
     ot("\n"); return 0;\r
   }\r
@@ -344,10 +354,11 @@ int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)
   {\r
     int asl=0;\r
 \r
-    if (top) asl=shift;\r
+    if (type == earwt_shifted_up) asl = shift;\r
 \r
-    if (asl) ot("  mov r%d,r%d,asl #%d\n",v,a,asl);\r
-    else if (v!=a) ot("  mov r%d,r%d\n",v,a);\r
+    if (asl)         ot("  mov%s r%d,r%d,asl #%d\n",s,v,a,asl);\r
+    else if (v!=a)   ot("  mov%s r%d,r%d\n",s,v,a);\r
+    else if (set_nz) ot("  tst r%d,r%d\n",v,v);\r
     ot("\n"); return 0;\r
   }\r
 \r
@@ -357,28 +368,34 @@ int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)
   // defaults to 1, as most things begins with a read\r
   earead_check_addrerr=1;\r
 \r
-  if (sign_extend)\r
+  if (type == earwt_sign_extend)\r
   {\r
     int d_reg=0;\r
     if (shift) {\r
-      ot("  mov r%d,r%d,asl #%d\n",v,d_reg,shift);\r
+      SignExtend(v, d_reg, size);\r
       d_reg=v;\r
+      flags_set=1;\r
     }\r
-    if (!top && shift) {\r
-      ot("  mov r%d,r%d,asr #%d\n",v,d_reg,shift);\r
-      d_reg=v;\r
+    if (d_reg != v) {\r
+      ot("  mov%s r%d,r%d\n",s,v,d_reg);\r
+      flags_set=1;\r
     }\r
-    if (d_reg != v)\r
-      ot("  mov r%d,r%d\n",v,d_reg);\r
   }\r
   else\r
   {\r
-    if (top && shift)\r
-      ot("  mov r%d,r0,asl #%d\n",v,shift);\r
-    else if (v!=0)\r
-      ot("  mov r%d,r0\n",v);\r
+    if (type == earwt_shifted_up && shift) {\r
+      ot("  mov%s r%d,r0,asl #%d\n",s,v,shift);\r
+      flags_set=1;\r
+    }\r
+    else if (v!=0) {\r
+      ot("  mov%s r%d,r0\n",s,v);\r
+      flags_set=1;\r
+    }\r
   }\r
 \r
+  if (set_nz&&!flags_set)\r
+    ot("  tst r%d,r%d\n",v,v);\r
+\r
   ot("\n"); return 0;\r
 }\r
 \r
@@ -388,15 +405,14 @@ int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend)
 // else r0-r3 are trashed\r
 // size values 0, 1, 2 ~ byte, word, long\r
 // r_ea is reg to store ea in (-1 means ea is not needed), r is dst reg\r
-// if sign_extend is 0, non-32bit values will have MS bits undefined\r
-int EaCalcRead(int r_ea,int r,int ea,int size,int mask,int sign_extend)\r
+int EaCalcRead(int r_ea,int r,int ea,int size,int mask,EaRWType type,int set_nz)\r
 {\r
   if (ea<0x10)\r
   {\r
     if (r_ea==-1)\r
     {\r
       r_ea=r;\r
-      if (!sign_extend) size=2;\r
+      if (type == earwt_msb_dont_care) size=2;\r
     }\r
   }\r
   else if (ea==0x3c) // #imm\r
@@ -408,17 +424,12 @@ int EaCalcRead(int r_ea,int r,int ea,int size,int mask,int sign_extend)
     if (r_ea==-1) r_ea=0;\r
   }\r
 \r
-  EaCalc (r_ea,mask,ea,size,0,sign_extend);\r
-  EaRead (r_ea,   r,ea,size,mask,0,sign_extend);\r
+  EaCalc (r_ea,mask,ea,size,type);\r
+  EaRead (r_ea,   r,ea,size,mask,type,set_nz);\r
 \r
   return 0;\r
 }\r
 \r
-int EaCalcReadNoSE(int r_ea,int r,int ea,int size,int mask)\r
-{\r
-  return EaCalcRead(r_ea,r,ea,size,mask,0);\r
-}\r
-\r
 // Return 1 if we can read this ea\r
 int EaCanRead(int ea,int size)\r
 {\r
@@ -439,28 +450,28 @@ int EaCanRead(int ea,int size)
 // Write effective address (ARM Register 'a') with ARM register 'v'\r
 // Trashes r0-r3,r12,lr; 'a' can be 0 or 2+, 'v' can be 1 or higher\r
 // If a==0 and v==1 it's faster though.\r
-int EaWrite(int a,int v,int ea,int size,int mask,int top,int sign_extend_ea)\r
+int EaWrite(int a,int v,int ea,int size,int mask,EaRWType type)\r
 {\r
   char text[32]="";\r
   int shift=0;\r
 \r
   if(a == 1) { printf("Error! EaWrite a==1 !\n"); return 1; }\r
 \r
-  if (top) shift=32-(8<<size);\r
+  if (type == earwt_shifted_up) shift=32-(8<<size);\r
 \r
   DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address\r
 \r
   if (ea<0x10)\r
   {\r
     int lsl=0,low=0,i;\r
-    if (size>=2||(size==0&&(top||!sign_extend_ea))) {\r
+    if (size >= 2 || (size == 0 && type != earwt_sign_extend)) {\r
       if(mask)\r
         for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is\r
       lsl=2-low; // Having a lsl #x here saves one opcode\r
     }\r
 \r
     ot(";@ EaWrite: r%d into register[r%d]:\n",v,a);\r
-    if (shift)  ot("  mov r%d,r%d,asr #%d\n",v,v,shift);\r
+    if (shift)  ot("  mov r%d,r%d,lsr #%d\n",v,v,shift);\r
 \r
     if      (lsl>0) ot("  str%s r%d,[r7,r%d,lsl #%i]\n",Narm[size&3],v,a,lsl);\r
     else if (lsl<0) ot("  str%s r%d,[r7,r%d,lsr #%i]\n",Narm[size&3],v,a,-lsl);\r
@@ -473,8 +484,29 @@ int EaWrite(int a,int v,int ea,int size,int mask,int top,int sign_extend_ea)
 \r
   if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; }\r
 \r
-  if (shift)     ot("  mov r1,r%d,asr #%d\n",v,shift);\r
-  else if (v!=1) ot("  mov r1,r%d\n",v);\r
+  if (shift)\r
+  {\r
+    ot("  mov r1,r%d,lsr #%d\n",v,shift);\r
+  }\r
+  else if (v != 1 || (size < 2 && type != earwt_zero_extend))\r
+  {\r
+    switch (size) {\r
+    case 0:\r
+      ot("  and r1,r%d,#0xff\n",v);\r
+      break;\r
+    case 1:\r
+      if (type != earwt_zero_extend)\r
+      {\r
+        ZeroExtend(1, v, size);\r
+        break;\r
+      }\r
+      // fallthrough\r
+    case 2:\r
+    default:\r
+      ot("  mov r1,r%d\n",v);\r
+      break;\r
+    }\r
+  }\r
 \r
   MemHandler(1,size,a,eawrite_check_addrerr); // Call write handler\r
 \r