1896 |
|
comprintf("\tint highmask;\n" |
1897 |
|
"\tint width;\n" |
1898 |
|
"\tint cdata=scratchie++;\n" |
1899 |
< |
"\tint tmpcnt=scratchie++;\n" |
1900 |
< |
"\tint highshift=scratchie++;\n"); |
1901 |
< |
comprintf("\tmov_l_rr(tmpcnt,cnt);\n" |
1902 |
< |
"\tand_l_ri(tmpcnt,63);\n" |
1903 |
< |
"\tmov_l_ri(cdata,0);\n" |
1904 |
< |
"\tcmov_l_rr(cdata,data,5);\n"); |
1905 |
< |
/* cdata is now either data (for shift count!=0) or |
1906 |
< |
0 (for shift count==0) */ |
1907 |
< |
switch(curi->size) { |
1908 |
< |
case sz_byte: comprintf("\tshra_b_rr(data,cnt);\n" |
1909 |
< |
"\thighmask=0x38;\n" |
1910 |
< |
"\twidth=8;\n"); |
1911 |
< |
break; |
1912 |
< |
case sz_word: comprintf("\tshra_w_rr(data,cnt);\n" |
1913 |
< |
"\thighmask=0x30;\n" |
1914 |
< |
"\twidth=16;\n"); |
1915 |
< |
break; |
1916 |
< |
case sz_long: comprintf("\tshra_l_rr(data,cnt);\n" |
1917 |
< |
"\thighmask=0x20;\n" |
1918 |
< |
"\twidth=32;\n"); |
1919 |
< |
break; |
1920 |
< |
default: abort(); |
1921 |
< |
} |
1922 |
< |
comprintf("test_l_ri(cnt,highmask);\n" |
1923 |
< |
"mov_l_ri(highshift,0);\n" |
1924 |
< |
"mov_l_ri(scratchie,width/2);\n" |
1925 |
< |
"cmov_l_rr(highshift,scratchie,5);\n"); |
1926 |
< |
/* The x86 masks out bits, so we now make sure that things |
1927 |
< |
really get shifted as much as planned */ |
1899 |
> |
"\tint sdata=scratchie++;\n" |
1900 |
> |
"\tint tmpcnt=scratchie++;\n"); |
1901 |
> |
comprintf("\tmov_l_rr(sdata,data);\n" |
1902 |
> |
"\tmov_l_rr(cdata,data);\n" |
1903 |
> |
"\tmov_l_rr(tmpcnt,cnt);\n"); |
1904 |
> |
switch (curi->size) { |
1905 |
> |
case sz_byte: comprintf("\tshra_b_ri(sdata,7);\n"); break; |
1906 |
> |
case sz_word: comprintf("\tshra_w_ri(sdata,15);\n"); break; |
1907 |
> |
case sz_long: comprintf("\tshra_l_ri(sdata,31);\n"); break; |
1908 |
> |
default: abort(); |
1909 |
> |
} |
1910 |
> |
/* sdata is now the MSB propagated to all bits for the |
1911 |
> |
register of specified size */ |
1912 |
> |
comprintf("\tand_l_ri(tmpcnt,63);\n"); |
1913 |
|
switch(curi->size) { |
1914 |
< |
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; |
1915 |
< |
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; |
1916 |
< |
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; |
1917 |
< |
default: abort(); |
1914 |
> |
case sz_byte: comprintf("\tshra_b_rr(data,tmpcnt);\n" |
1915 |
> |
"\thighmask=0x38;\n"); |
1916 |
> |
break; |
1917 |
> |
case sz_word: comprintf("\tshra_w_rr(data,tmpcnt);\n" |
1918 |
> |
"\thighmask=0x30;\n"); |
1919 |
> |
break; |
1920 |
> |
case sz_long: comprintf("\tshra_l_rr(data,tmpcnt);\n" |
1921 |
> |
"\thighmask=0x20;\n"); |
1922 |
> |
break; |
1923 |
|
} |
1924 |
< |
/* And again */ |
1925 |
< |
switch(curi->size) { |
1926 |
< |
case sz_byte: comprintf("\tshra_b_rr(data,highshift);\n");break; |
1927 |
< |
case sz_word: comprintf("\tshra_w_rr(data,highshift);\n");break; |
1928 |
< |
case sz_long: comprintf("\tshra_l_rr(data,highshift);\n");break; |
1939 |
< |
default: abort(); |
1924 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); |
1925 |
> |
switch (curi->size) { |
1926 |
> |
case sz_byte: comprintf("\tcmov_b_rr(data,sdata,NATIVE_CC_NE);\n"); break; |
1927 |
> |
case sz_word: comprintf("\tcmov_w_rr(data,sdata,NATIVE_CC_NE);\n"); break; |
1928 |
> |
case sz_long: comprintf("\tcmov_l_rr(data,sdata,NATIVE_CC_NE);\n"); break; |
1929 |
|
} |
1930 |
|
|
1931 |
|
/* Result of shift is now in data. Now we need to determine |
1932 |
|
the carry by shifting cdata one less */ |
1933 |
+ |
/* NOTE: carry bit is cleared if shift count is zero */ |
1934 |
+ |
comprintf("\tmov_l_ri(scratchie,0);\n" |
1935 |
+ |
"\ttest_l_rr(tmpcnt,tmpcnt);\n" |
1936 |
+ |
"\tcmov_l_rr(sdata,scratchie,NATIVE_CC_EQ);\n" |
1937 |
+ |
"\tforget_about(scratchie);\n"); |
1938 |
|
comprintf("\tsub_l_ri(tmpcnt,1);\n"); |
1939 |
|
switch(curi->size) { |
1940 |
|
case sz_byte: comprintf("\tshra_b_rr(cdata,tmpcnt);\n");break; |
1943 |
|
default: abort(); |
1944 |
|
} |
1945 |
|
/* If the shift count was higher than the width, we need |
1946 |
< |
to pick up the sign from data */ |
1947 |
< |
comprintf("test_l_ri(tmpcnt,highmask);\n" |
1948 |
< |
"cmov_l_rr(cdata,data,5);\n"); |
1949 |
< |
/* And create the flags */ |
1946 |
> |
to pick up the sign from original data (sdata) */ |
1947 |
> |
/* NOTE: for shift count of zero, the following holds |
1948 |
> |
true and cdata contains 0 so that carry bit is cleared */ |
1949 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n" |
1950 |
> |
"\tforget_about(tmpcnt);\n" |
1951 |
> |
"\tcmov_l_rr(cdata,sdata,NATIVE_CC_NE);\n"); |
1952 |
> |
|
1953 |
> |
/* And create the flags (preserve X flag if shift count is zero) */ |
1954 |
> |
comprintf("\ttest_l_ri(cnt,63);\n" |
1955 |
> |
"\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); |
1956 |
|
comprintf("\tstart_needflags();\n"); |
1957 |
|
comprintf("\tif (needed_flags & FLAG_ZNV)\n"); |
1958 |
|
switch(curi->size) { |
1963 |
|
comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ |
1964 |
|
comprintf("\t live_flags();\n"); |
1965 |
|
comprintf("\t end_needflags();\n"); |
1966 |
– |
comprintf("\t duplicate_carry();\n"); |
1966 |
|
comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); |
1967 |
|
genastore ("data", curi->dmode, "dstreg", curi->size, "data"); |
1968 |
|
} |
2213 |
|
comprintf("\tmov_l_rr(tmpcnt,cnt);\n" |
2214 |
|
"\tand_l_ri(tmpcnt,63);\n" |
2215 |
|
"\tmov_l_ri(cdata,0);\n" |
2216 |
< |
"\tcmov_l_rr(cdata,data,5);\n"); |
2216 |
> |
"\tcmov_l_rr(cdata,data,NATIVE_CC_NE);\n"); |
2217 |
|
/* cdata is now either data (for shift count!=0) or |
2218 |
|
0 (for shift count==0) */ |
2219 |
|
switch(curi->size) { |
2220 |
< |
case sz_byte: comprintf("\tshrl_b_rr(data,cnt);\n" |
2220 |
> |
case sz_byte: comprintf("\tshrl_b_rr(data,tmpcnt);\n" |
2221 |
|
"\thighmask=0x38;\n"); |
2222 |
|
break; |
2223 |
< |
case sz_word: comprintf("\tshrl_w_rr(data,cnt);\n" |
2223 |
> |
case sz_word: comprintf("\tshrl_w_rr(data,tmpcnt);\n" |
2224 |
|
"\thighmask=0x30;\n"); |
2225 |
|
break; |
2226 |
< |
case sz_long: comprintf("\tshrl_l_rr(data,cnt);\n" |
2226 |
> |
case sz_long: comprintf("\tshrl_l_rr(data,tmpcnt);\n" |
2227 |
|
"\thighmask=0x20;\n"); |
2228 |
|
break; |
2229 |
|
default: abort(); |
2230 |
|
} |
2231 |
< |
comprintf("test_l_ri(cnt,highmask);\n" |
2232 |
< |
"mov_l_ri(scratchie,0);\n" |
2233 |
< |
"cmov_l_rr(scratchie,data,4);\n"); |
2234 |
< |
switch(curi->size) { |
2235 |
< |
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; |
2236 |
< |
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; |
2237 |
< |
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; |
2238 |
< |
default: abort(); |
2231 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n" |
2232 |
> |
"\rmov_l_ri(scratchie,0);\n"); |
2233 |
> |
if (curi->size == sz_long) |
2234 |
> |
comprintf("\tcmov_l_rr(data,scratchie,NATIVE_CC_NE);\n"); |
2235 |
> |
else { |
2236 |
> |
comprintf("\tcmov_l_rr(scratchie,data,NATIVE_CC_EQ);\n"); |
2237 |
> |
switch(curi->size) { |
2238 |
> |
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; |
2239 |
> |
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; |
2240 |
> |
default: abort(); |
2241 |
> |
} |
2242 |
|
} |
2243 |
|
/* Result of shift is now in data. Now we need to determine |
2244 |
|
the carry by shifting cdata one less */ |
2245 |
|
comprintf("\tsub_l_ri(tmpcnt,1);\n"); |
2246 |
< |
switch(curi->size) { |
2247 |
< |
case sz_byte: comprintf("\tshrl_b_rr(cdata,tmpcnt);\n");break; |
2248 |
< |
case sz_word: comprintf("\tshrl_w_rr(cdata,tmpcnt);\n");break; |
2249 |
< |
case sz_long: comprintf("\tshrl_l_rr(cdata,tmpcnt);\n");break; |
2250 |
< |
default: abort(); |
2251 |
< |
} |
2252 |
< |
comprintf("test_l_ri(tmpcnt,highmask);\n" |
2253 |
< |
"mov_l_ri(scratchie,0);\n" |
2254 |
< |
"cmov_l_rr(cdata,scratchie,5);\n"); |
2255 |
< |
/* And create the flags */ |
2246 |
> |
comprintf("\tshrl_l_rr(cdata,tmpcnt);\n"); |
2247 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); |
2248 |
> |
comprintf("\tforget_about(tmpcnt);\n"); |
2249 |
> |
if (curi->size != sz_long) /* scratchie is still live for LSR.L */ |
2250 |
> |
comprintf("\tmov_l_ri(scratchie,0);\n"); |
2251 |
> |
comprintf("\tcmov_l_rr(cdata,scratchie,NATIVE_CC_NE);\n"); |
2252 |
> |
comprintf("\tforget_about(scratchie);\n"); |
2253 |
> |
/* And create the flags (preserve X flag if shift count is zero) */ |
2254 |
> |
comprintf("\ttest_l_ri(cnt,63);\n" |
2255 |
> |
"\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); |
2256 |
|
comprintf("\tstart_needflags();\n"); |
2257 |
|
comprintf("\tif (needed_flags & FLAG_ZNV)\n"); |
2258 |
|
switch(curi->size) { |
2263 |
|
comprintf("\t bt_l_ri(cdata,0);\n"); /* Set C */ |
2264 |
|
comprintf("\t live_flags();\n"); |
2265 |
|
comprintf("\t end_needflags();\n"); |
2264 |
– |
comprintf("\t duplicate_carry();\n"); |
2266 |
|
comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); |
2267 |
|
genastore ("data", curi->dmode, "dstreg", curi->size, "data"); |
2268 |
|
} |
2351 |
|
comprintf("\tmov_l_rr(tmpcnt,cnt);\n" |
2352 |
|
"\tand_l_ri(tmpcnt,63);\n" |
2353 |
|
"\tmov_l_ri(cdata,0);\n" |
2354 |
< |
"\tcmov_l_rr(cdata,data,5);\n"); |
2354 |
> |
"\tcmov_l_rr(cdata,data,NATIVE_CC_NE);\n"); |
2355 |
|
/* cdata is now either data (for shift count!=0) or |
2356 |
|
0 (for shift count==0) */ |
2357 |
|
switch(curi->size) { |
2358 |
< |
case sz_byte: comprintf("\tshll_b_rr(data,cnt);\n" |
2358 |
> |
case sz_byte: comprintf("\tshll_b_rr(data,tmpcnt);\n" |
2359 |
|
"\thighmask=0x38;\n"); |
2360 |
|
break; |
2361 |
< |
case sz_word: comprintf("\tshll_w_rr(data,cnt);\n" |
2361 |
> |
case sz_word: comprintf("\tshll_w_rr(data,tmpcnt);\n" |
2362 |
|
"\thighmask=0x30;\n"); |
2363 |
|
break; |
2364 |
< |
case sz_long: comprintf("\tshll_l_rr(data,cnt);\n" |
2364 |
> |
case sz_long: comprintf("\tshll_l_rr(data,tmpcnt);\n" |
2365 |
|
"\thighmask=0x20;\n"); |
2366 |
|
break; |
2367 |
|
default: abort(); |
2368 |
|
} |
2369 |
< |
comprintf("test_l_ri(cnt,highmask);\n" |
2370 |
< |
"mov_l_ri(scratchie,0);\n" |
2371 |
< |
"cmov_l_rr(scratchie,data,4);\n"); |
2372 |
< |
switch(curi->size) { |
2373 |
< |
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; |
2374 |
< |
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; |
2375 |
< |
case sz_long: comprintf("\tmov_l_rr(data,scratchie);\n");break; |
2376 |
< |
default: abort(); |
2369 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n" |
2370 |
> |
"\tmov_l_ri(scratchie,0);\n"); |
2371 |
> |
if (curi->size == sz_long) |
2372 |
> |
comprintf("\tcmov_l_rr(data,scratchie,NATIVE_CC_NE);\n"); |
2373 |
> |
else { |
2374 |
> |
comprintf("\tcmov_l_rr(scratchie,data,NATIVE_CC_EQ);\n"); |
2375 |
> |
switch(curi->size) { |
2376 |
> |
case sz_byte: comprintf("\tmov_b_rr(data,scratchie);\n");break; |
2377 |
> |
case sz_word: comprintf("\tmov_w_rr(data,scratchie);\n");break; |
2378 |
> |
default: abort(); |
2379 |
> |
} |
2380 |
|
} |
2381 |
|
/* Result of shift is now in data. Now we need to determine |
2382 |
|
the carry by shifting cdata one less */ |
2383 |
|
comprintf("\tsub_l_ri(tmpcnt,1);\n"); |
2384 |
< |
switch(curi->size) { |
2385 |
< |
case sz_byte: comprintf("\tshll_b_rr(cdata,tmpcnt);\n");break; |
2386 |
< |
case sz_word: comprintf("\tshll_w_rr(cdata,tmpcnt);\n");break; |
2387 |
< |
case sz_long: comprintf("\tshll_l_rr(cdata,tmpcnt);\n");break; |
2388 |
< |
default: abort(); |
2384 |
> |
comprintf("\tshll_l_rr(cdata,tmpcnt);\n"); |
2385 |
> |
comprintf("\ttest_l_ri(tmpcnt,highmask);\n"); |
2386 |
> |
comprintf("\tforget_about(tmpcnt);\n"); |
2387 |
> |
if (curi->size != sz_long) /* scratchie is still live for LSL.L */ |
2388 |
> |
comprintf("\tmov_l_ri(scratchie,0);\n"); |
2389 |
> |
comprintf("\tcmov_l_rr(cdata,scratchie,NATIVE_CC_NE);\n"); |
2390 |
> |
comprintf("\tforget_about(scratchie);\n"); |
2391 |
> |
/* And create the flags (preserve X flag if shift count is zero) */ |
2392 |
> |
switch (curi->size) { |
2393 |
> |
case sz_byte: comprintf("\tshrl_l_ri(cdata,7);\n"); break; |
2394 |
> |
case sz_word: comprintf("\tshrl_l_ri(cdata,15);\n"); break; |
2395 |
> |
case sz_long: comprintf("\tshrl_l_ri(cdata,31);\n"); break; |
2396 |
|
} |
2397 |
< |
comprintf("test_l_ri(tmpcnt,highmask);\n" |
2398 |
< |
"mov_l_ri(scratchie,0);\n" |
2388 |
< |
"cmov_l_rr(cdata,scratchie,5);\n"); |
2389 |
< |
/* And create the flags */ |
2397 |
> |
comprintf("\ttest_l_ri(cnt,63);\n" |
2398 |
> |
"\tcmov_l_rr(FLAGX,cdata,NATIVE_CC_NE);\n"); |
2399 |
|
comprintf("\tstart_needflags();\n"); |
2400 |
|
comprintf("\tif (needed_flags & FLAG_ZNV)\n"); |
2401 |
|
switch(curi->size) { |
2402 |
< |
case sz_byte: comprintf("\t test_b_rr(data,data);\n"); |
2403 |
< |
comprintf("\t bt_l_ri(cdata,7);\n"); break; |
2404 |
< |
case sz_word: comprintf("\t test_w_rr(data,data);\n"); |
2396 |
< |
comprintf("\t bt_l_ri(cdata,15);\n"); break; |
2397 |
< |
case sz_long: comprintf("\t test_l_rr(data,data);\n"); |
2398 |
< |
comprintf("\t bt_l_ri(cdata,31);\n"); break; |
2402 |
> |
case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break; |
2403 |
> |
case sz_word: comprintf("\t test_w_rr(data,data);\n"); break; |
2404 |
> |
case sz_long: comprintf("\t test_l_rr(data,data);\n"); break; |
2405 |
|
} |
2406 |
+ |
comprintf("\t bt_l_ri(cdata,0);\n"); |
2407 |
|
comprintf("\t live_flags();\n"); |
2408 |
|
comprintf("\t end_needflags();\n"); |
2402 |
– |
comprintf("\t duplicate_carry();\n"); |
2409 |
|
comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n"); |
2410 |
|
genastore ("data", curi->dmode, "dstreg", curi->size, "data"); |
2411 |
|
} |