History

arm64-gen.c: Avoid some cases of undefined behaviour.

Also make some functions more portable.

Edmund Grimley Evans committed 11 years ago

Commit a7334f71 parent c52128c1 file · +55 −44Browse files

Unified · Split

arm64-gen.c+55−44
@@ -286,26 +286,28 @@ static void arm64_spoff(int reg, uint64_t off) · 285 unmodified lines
286 }286 }
287}287}
288 288
289static void arm64_ldrx(int sg, int sz, int dst, int bas, uint64_t off)289static void arm64_ldrx(int sg, int sz_, int dst, int bas, uint64_t off)
290{290{
291 uint32_t sz = sz_;
291 if (sz >= 2)292 if (sz >= 2)
292 sg = 0;293 sg = 0;
293 if (!(off & ~(0xfff << sz)))294 if (!(off & ~((uint32_t)0xfff << sz)))
294 o(0x39400000 | dst | bas << 5 | off << (10 - sz) |295 o(0x39400000 | dst | bas << 5 | off << (10 - sz) |
295 !!sg << 23 | sz << 30); // ldr(*) x(dst),[x(bas),#(off)]296 (uint32_t)!!sg << 23 | sz << 30); // ldr(*) x(dst),[x(bas),#(off)]
296 else if (off < 256 || -off <= 256)297 else if (off < 256 || -off <= 256)
297 o(0x38400000 | dst | bas << 5 | (off & 511) << 12 |298 o(0x38400000 | dst | bas << 5 | (off & 511) << 12 |
298 !!sg << 23 | sz << 30); // ldur(*) x(dst),[x(bas),#(off)]299 (uint32_t)!!sg << 23 | sz << 30); // ldur(*) x(dst),[x(bas),#(off)]
299 else {300 else {
300 arm64_movimm(30, off); // use x30 for offset301 arm64_movimm(30, off); // use x30 for offset
301 o(0x38206800 | dst | bas << 5 | 30 << 16 |302 o(0x38206800 | dst | bas << 5 | (uint32_t)30 << 16 |
302 (!!sg + 1) << 22 | sz << 30); // ldr(*) x(dst),[x(bas),x30]303 (uint32_t)(!!sg + 1) << 22 | sz << 30); // ldr(*) x(dst),[x(bas),x30]
303 }304 }
304}305}
305 306
306static void arm64_ldrv(int sz, int dst, int bas, uint64_t off)307static void arm64_ldrv(int sz_, int dst, int bas, uint64_t off)
307{308{
308 if (!(off & ~(0xfff << sz)))309 uint32_t sz = sz_;
310 if (!(off & ~((uint32_t)0xfff << sz)))
309 o(0x3d400000 | dst | bas << 5 | off << (10 - sz) |311 o(0x3d400000 | dst | bas << 5 | off << (10 - sz) |
310 (sz & 4) << 21 | (sz & 3) << 30); // ldr (s|d|q)(dst),[x(bas),#(off)]312 (sz & 4) << 21 | (sz & 3) << 30); // ldr (s|d|q)(dst),[x(bas),#(off)]
311 else if (off < 256 || -off <= 256)313 else if (off < 256 || -off <= 256)
@@ -313,13 +315,14 @@ static void arm64_ldrv(int sz, int dst, int bas, uint64_t off) · 1 unmodified line
313 (sz & 4) << 21 | (sz & 3) << 30); // ldur (s|d|q)(dst),[x(bas),#(off)]315 (sz & 4) << 21 | (sz & 3) << 30); // ldur (s|d|q)(dst),[x(bas),#(off)]
314 else {316 else {
315 arm64_movimm(30, off); // use x30 for offset317 arm64_movimm(30, off); // use x30 for offset
316 o(0x3c606800 | dst | bas << 5 | 30 << 16 | sz << 30 | (sz & 4) << 21);318 o(0x3c606800 | dst | bas << 5 | (uint32_t)30 << 16 |
317 // ldr (s|d|q)(dst),[x(bas),x30]319 sz << 30 | (sz & 4) << 21); // ldr (s|d|q)(dst),[x(bas),x30]
318 }320 }
319}321}
320 322
321static void arm64_ldrs(int reg, int size)323static void arm64_ldrs(int reg_, int size)
322{324{
325 uint32_t reg = reg_;
323 // Use x30 for intermediate value in some cases.326 // Use x30 for intermediate value in some cases.
324 switch (size) {327 switch (size) {
325 default: assert(0); break;328 default: assert(0); break;
@@ -395,9 +398,10 @@ static void arm64_ldrs(int reg, int size) · 69 unmodified lines
395 }398 }
396}399}
397 400
398static void arm64_strx(int sz, int dst, int bas, uint64_t off)401static void arm64_strx(int sz_, int dst, int bas, uint64_t off)
399{402{
400 if (!(off & ~(0xfff << sz)))403 uint32_t sz = sz_;
404 if (!(off & ~((uint32_t)0xfff << sz)))
401 o(0x39000000 | dst | bas << 5 | off << (10 - sz) | sz << 30);405 o(0x39000000 | dst | bas << 5 | off << (10 - sz) | sz << 30);
402 // str(*) x(dst),[x(bas],#(off)]406 // str(*) x(dst),[x(bas],#(off)]
403 else if (off < 256 || -off <= 256)407 else if (off < 256 || -off <= 256)
@@ -405,14 +409,15 @@ static void arm64_strx(int sz, int dst, int bas, uint64_t off) · 1 unmodified line
405 // stur(*) x(dst),[x(bas],#(off)]409 // stur(*) x(dst),[x(bas],#(off)]
406 else {410 else {
407 arm64_movimm(30, off); // use x30 for offset411 arm64_movimm(30, off); // use x30 for offset
408 o(0x38206800 | dst | bas << 5 | 30 << 16 | sz << 30);412 o(0x38206800 | dst | bas << 5 | (uint32_t)30 << 16 | sz << 30);
409 // str(*) x(dst),[x(bas),x30]413 // str(*) x(dst),[x(bas),x30]
410 }414 }
411}415}
412 416
413static void arm64_strv(int sz, int dst, int bas, uint64_t off)417static void arm64_strv(int sz_, int dst, int bas, uint64_t off)
414{418{
415 if (!(off & ~(0xfff << sz)))419 uint32_t sz = sz_;
420 if (!(off & ~((uint32_t)0xfff << sz)))
416 o(0x3d000000 | dst | bas << 5 | off << (10 - sz) |421 o(0x3d000000 | dst | bas << 5 | off << (10 - sz) |
417 (sz & 4) << 21 | (sz & 3) << 30); // str (s|d|q)(dst),[x(bas),#(off)]422 (sz & 4) << 21 | (sz & 3) << 30); // str (s|d|q)(dst),[x(bas),#(off)]
418 else if (off < 256 || -off <= 256)423 else if (off < 256 || -off <= 256)
@@ -420,8 +425,8 @@ static void arm64_strv(int sz, int dst, int bas, uint64_t off) · 1 unmodified line
420 (sz & 4) << 21 | (sz & 3) << 30); // stur (s|d|q)(dst),[x(bas),#(off)]425 (sz & 4) << 21 | (sz & 3) << 30); // stur (s|d|q)(dst),[x(bas),#(off)]
421 else {426 else {
422 arm64_movimm(30, off); // use x30 for offset427 arm64_movimm(30, off); // use x30 for offset
423 o(0x3c206800 | dst | bas << 5 | 30 << 16 | sz << 30 | (sz & 4) << 21);428 o(0x3c206800 | dst | bas << 5 | (uint32_t)30 << 16 |
424 // str (s|d|q)(dst),[x(bas),x30]429 sz << 30 | (sz & 4) << 21); // str (s|d|q)(dst),[x(bas),x30]
425 }430 }
426}431}
427 432
@@ -458,7 +463,8 @@ ST_FUNC void load(int r, SValue *sv) · 30 unmodified lines
458 int svtt = sv->type.t;463 int svtt = sv->type.t;
459 int svr = sv->r & ~VT_LVAL_TYPE;464 int svr = sv->r & ~VT_LVAL_TYPE;
460 int svrv = svr & VT_VALMASK;465 int svrv = svr & VT_VALMASK;
461 uint64_t svcul = (int32_t)sv->c.ul;466 uint64_t svcul = (uint32_t)sv->c.ul;
467 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
462 468
463 if (svr == (VT_LOCAL | VT_LVAL)) {469 if (svr == (VT_LOCAL | VT_LVAL)) {
464 if (IS_FREG(r))470 if (IS_FREG(r))
@@ -519,7 +525,7 @@ ST_FUNC void load(int r, SValue *sv) · 54 unmodified lines
519 o(0xd10003a0 | intr(r) | -svcul << 10); // sub x(r),x29,#...525 o(0xd10003a0 | intr(r) | -svcul << 10); // sub x(r),x29,#...
520 else {526 else {
521 arm64_movimm(30, -svcul); // use x30 for offset527 arm64_movimm(30, -svcul); // use x30 for offset
522 o(0xcb0003a0 | intr(r) | 30 << 16); // sub x(r),x29,x30528 o(0xcb0003a0 | intr(r) | (uint32_t)30 << 16); // sub x(r),x29,x30
523 }529 }
524 return;530 return;
525 }531 }
@@ -552,7 +558,8 @@ ST_FUNC void store(int r, SValue *sv) · 26 unmodified lines
552 int svtt = sv->type.t;558 int svtt = sv->type.t;
553 int svr = sv->r & ~VT_LVAL_TYPE;559 int svr = sv->r & ~VT_LVAL_TYPE;
554 int svrv = svr & VT_VALMASK;560 int svrv = svr & VT_VALMASK;
555 uint64_t svcul = (int32_t)sv->c.ul;561 uint64_t svcul = (uint32_t)sv->c.ul;
562 svcul = svcul >> 31 & 1 ? svcul - ((uint64_t)1 << 32) : svcul;
556 563
557 if (svr == (VT_LOCAL | VT_LVAL)) {564 if (svr == (VT_LOCAL | VT_LVAL)) {
558 if (IS_FREG(r))565 if (IS_FREG(r))
@@ -594,7 +601,7 @@ static void arm64_gen_bl_or_b(int b) · 35 unmodified lines
594 o(0x94000000); // bl .601 o(0x94000000); // bl .
595 }602 }
596 else603 else
597 o(0xd61f0000 | !b << 21 | intr(gv(RC_R30)) << 5); // br/blr604 o(0xd61f0000 | (uint32_t)!b << 21 | intr(gv(RC_R30)) << 5); // br/blr
598}605}
599 606
600static int arm64_hfa_aux(CType *type, int *fsize, int num)607static int arm64_hfa_aux(CType *type, int *fsize, int num)
@@ -930,7 +937,7 @@ ST_FUNC void gfunc_call(int nb_args) · 329 unmodified lines
930 else if (a[i] < 32) {937 else if (a[i] < 32) {
931 // value in floating-point registers938 // value in floating-point registers
932 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {939 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
933 int j, sz, n = arm64_hfa(&vtop->type, &sz);940 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
934 vtop->type.t = VT_PTR;941 vtop->type.t = VT_PTR;
935 gaddrof();942 gaddrof();
936 gv(RC_R30);943 gv(RC_R30);
@@ -968,7 +975,7 @@ ST_FUNC void gfunc_call(int nb_args) · 31 unmodified lines
968 if (bt == VT_BYTE || bt == VT_SHORT)975 if (bt == VT_BYTE || bt == VT_SHORT)
969 // Promote small integers:976 // Promote small integers:
970 o(0x13001c00 | (bt == VT_SHORT) << 13 |977 o(0x13001c00 | (bt == VT_SHORT) << 13 |
971 !!(rt & VT_UNSIGNED) << 30); // [su]xt[bh] w0,w0978 (uint32_t)!!(rt & VT_UNSIGNED) << 30); // [su]xt[bh] w0,w0
972 else if (bt == VT_STRUCT && !(a[0] & 1)) {979 else if (bt == VT_STRUCT && !(a[0] & 1)) {
973 // A struct was returned in registers, so write it out:980 // A struct was returned in registers, so write it out:
974 gv(RC_R(8));981 gv(RC_R(8));
@@ -983,7 +990,7 @@ ST_FUNC void gfunc_call(int nb_args) · 8 unmodified lines
983 990
984 }991 }
985 else if (a[0] == 16) {992 else if (a[0] == 16) {
986 int j, sz, n = arm64_hfa(return_type, &sz);993 uint32_t j, sz, n = arm64_hfa(return_type, &sz);
987 for (j = 0; j < n; j++)994 for (j = 0; j < n; j++)
988 o(0x3d000100 |995 o(0x3d000100 |
989 (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |996 (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
@@ -1053,14 +1060,14 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 63 unmodified lines
1053 (!(a[i] & 1) && size > 8)) * 8;1060 (!(a[i] & 1) && size > 8)) * 8;
1054 }1061 }
1055 else if (a[i] < 32) {1062 else if (a[i] < 32) {
1056 int hfa = arm64_hfa(&sym->type, 0);1063 uint32_t hfa = arm64_hfa(&sym->type, 0);
1057 arm64_func_va_list_vr_offs = (a[i] / 2 - 16 +1064 arm64_func_va_list_vr_offs = (a[i] / 2 - 16 +
1058 (hfa ? hfa : 1)) * 16;1065 (hfa ? hfa : 1)) * 16;
1059 }1066 }
1060 1067
1061 // HFAs of float and double need to be written differently:1068 // HFAs of float and double need to be written differently:
1062 if (16 <= a[i] && a[i] < 32 && (sym->type.t & VT_BTYPE) == VT_STRUCT) {1069 if (16 <= a[i] && a[i] < 32 && (sym->type.t & VT_BTYPE) == VT_STRUCT) {
1063 int j, sz, k = arm64_hfa(&sym->type, &sz);1070 uint32_t j, sz, k = arm64_hfa(&sym->type, &sz);
1064 if (sz < 16)1071 if (sz < 16)
1065 for (j = 0; j < k; j++) {1072 for (j = 0; j < k; j++) {
1066 o(0x3d0003e0 | -(sz & 8) << 27 | (sz & 4) << 29 |1073 o(0x3d0003e0 | -(sz & 8) << 27 | (sz & 4) << 29 |
@@ -1196,7 +1203,8 @@ ST_FUNC void gen_va_arg(CType *t) · 129 unmodified lines
1196 }1203 }
1197}1204}
1198 1205
1199ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize)1206ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
1207 int *align, int *regsize)
1200{1208{
1201 return 0;1209 return 0;
1202}1210}
@@ -1231,7 +1239,7 @@ ST_FUNC void greturn(void) · 28 unmodified lines
1231 }1239 }
1232 case 16:1240 case 16:
1233 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {1241 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1234 int j, sz, n = arm64_hfa(&vtop->type, &sz);1242 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
1235 gaddrof();1243 gaddrof();
1236 gv(RC_R(0));1244 gv(RC_R(0));
1237 for (j = 0; j < n; j++)1245 for (j = 0; j < n; j++)
@@ -1304,7 +1312,7 @@ ST_FUNC int gtst(int inv, int t) · 66 unmodified lines
1304{1312{
1305 int bt = vtop->type.t & VT_BTYPE;1313 int bt = vtop->type.t & VT_BTYPE;
1306 if (bt == VT_LDOUBLE) {1314 if (bt == VT_LDOUBLE) {
1307 int a, b, f = fltr(gv(RC_FLOAT));1315 uint32_t a, b, f = fltr(gv(RC_FLOAT));
1308 a = get_reg(RC_INT);1316 a = get_reg(RC_INT);
1309 vpushi(0);1317 vpushi(0);
1310 vtop[0].r = a;1318 vtop[0].r = a;
@@ -1318,13 +1326,13 @@ ST_FUNC int gtst(int inv, int t) · 7 unmodified lines
1318 --vtop;1326 --vtop;
1319 }1327 }
1320 else if (bt == VT_FLOAT || bt == VT_DOUBLE) {1328 else if (bt == VT_FLOAT || bt == VT_DOUBLE) {
1321 int a = fltr(gv(RC_FLOAT));1329 uint32_t a = fltr(gv(RC_FLOAT));
1322 o(0x1e202008 | a << 5 | (bt != VT_FLOAT) << 22); // fcmp1330 o(0x1e202008 | a << 5 | (bt != VT_FLOAT) << 22); // fcmp
1323 o(0x54000040 | !!inv); // b.eq/b.ne .+81331 o(0x54000040 | !!inv); // b.eq/b.ne .+8
1324 }1332 }
1325 else {1333 else {
1326 int ll = (bt == VT_PTR || bt == VT_LLONG);1334 uint32_t ll = (bt == VT_PTR || bt == VT_LLONG);
1327 int a = intr(gv(RC_INT));1335 uint32_t a = intr(gv(RC_INT));
1328 o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+81336 o(0x34000040 | a | !!inv << 24 | ll << 31); // cbz/cbnz wA,.+8
1329 }1337 }
1330 --vtop;1338 --vtop;
@@ -1362,7 +1370,7 @@ static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val, · 31 unmodified lines
1362 switch (op) {1370 switch (op) {
1363 1371
1364 case '+': {1372 case '+': {
1365 int s = l ? val >> 63 : val >> 31;1373 uint32_t s = l ? val >> 63 : val >> 31;
1366 val = s ? -val : val;1374 val = s ? -val : val;
1367 val = l ? val : (uint32_t)val;1375 val = l ? val : (uint32_t)val;
1368 if (!(val & ~(uint64_t)0xfff))1376 if (!(val & ~(uint64_t)0xfff))
@@ -1470,7 +1478,8 @@ static void arm64_gen_opil(int op, uint32_t l) · 101 unmodified lines
1470 case '%':1478 case '%':
1471 // Use x30 for quotient:1479 // Use x30 for quotient:
1472 o(0x1ac00c00 | l << 31 | 30 | a << 5 | b << 16); // sdiv1480 o(0x1ac00c00 | l << 31 | 30 | a << 5 | b << 16); // sdiv
1473 o(0x1b008000 | l << 31 | x | 30 << 5 | b << 16 | a << 10); // msub1481 o(0x1b008000 | l << 31 | x | (uint32_t)30 << 5 |
1482 b << 16 | a << 10); // msub
1474 break;1483 break;
1475 case '&':1484 case '&':
1476 o(0x0a000000 | l << 31 | x | a << 5 | b << 16); // and1485 o(0x0a000000 | l << 31 | x | a << 5 | b << 16); // and
@@ -1549,7 +1558,8 @@ static void arm64_gen_opil(int op, uint32_t l) · 72 unmodified lines
1549 case TOK_UMOD:1558 case TOK_UMOD:
1550 // Use x30 for quotient:1559 // Use x30 for quotient:
1551 o(0x1ac00800 | l << 31 | 30 | a << 5 | b << 16); // udiv1560 o(0x1ac00800 | l << 31 | 30 | a << 5 | b << 16); // udiv
1552 o(0x1b008000 | l << 31 | x | 30 << 5 | b << 16 | a << 10); // msub1561 o(0x1b008000 | l << 31 | x | (uint32_t)30 << 5 |
1562 b << 16 | a << 10); // msub
1553 break;1563 break;
1554 default:1564 default:
1555 assert(0);1565 assert(0);
@@ -1568,7 +1578,7 @@ ST_FUNC void gen_opl(int op) · 12 unmodified lines
1568 1578
1569ST_FUNC void gen_opf(int op)1579ST_FUNC void gen_opf(int op)
1570{1580{
1571 int x, a, b, dbl;1581 uint32_t x, a, b, dbl;
1572 1582
1573 if (vtop[0].type.t == VT_LDOUBLE) {1583 if (vtop[0].type.t == VT_LDOUBLE) {
1574 CType type = vtop[0].type;1584 CType type = vtop[0].type;
@@ -1596,7 +1606,7 @@ ST_FUNC void gen_opf(int op) · 21 unmodified lines
1596 vtop->type = type;1606 vtop->type = type;
1597 else {1607 else {
1598 o(0x7100001f); // cmp w0,#01608 o(0x7100001f); // cmp w0,#0
1599 o(0x1a9f07e0 | cond << 12); // cset w0,(cond)1609 o(0x1a9f07e0 | (uint32_t)cond << 12); // cset w0,(cond)
1600 }1610 }
1601 return;1611 return;
1602 }1612 }
@@ -1668,7 +1678,7 @@ ST_FUNC void gen_opf(int op) · 65 unmodified lines
1668// Generate sign extension from 32 to 64 bits:1678// Generate sign extension from 32 to 64 bits:
1669ST_FUNC void gen_cvt_sxtw(void)1679ST_FUNC void gen_cvt_sxtw(void)
1670{1680{
1671 int r = intr(gv(RC_INT));1681 uint32_t r = intr(gv(RC_INT));
1672 o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)1682 o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)
1673}1683}
1674 1684
@@ -1690,12 +1700,13 @@ ST_FUNC void gen_cvt_itof(int t) · 15 unmodified lines
1690 else {1700 else {
1691 int d, n = intr(gv(RC_INT));1701 int d, n = intr(gv(RC_INT));
1692 int s = !(vtop->type.t & VT_UNSIGNED);1702 int s = !(vtop->type.t & VT_UNSIGNED);
1693 int l = ((vtop->type.t & VT_BTYPE) == VT_LLONG);1703 uint32_t l = ((vtop->type.t & VT_BTYPE) == VT_LLONG);
1694 --vtop;1704 --vtop;
1695 d = get_reg(RC_FLOAT);1705 d = get_reg(RC_FLOAT);
1696 ++vtop;1706 ++vtop;
1697 vtop[0].r = d;1707 vtop[0].r = d;
1698 o(0x1e220000 | !s << 16 | (t != VT_FLOAT) << 22 | fltr(d) |1708 o(0x1e220000 | (uint32_t)!s << 16 |
1709 (uint32_t)(t != VT_FLOAT) << 22 | fltr(d) |
1699 l << 31 | n << 5); // [us]cvtf [sd](d),[wx](n)1710 l << 31 | n << 5); // [us]cvtf [sd](d),[wx](n)
1700 }1711 }
1701}1712}
@@ -1716,14 +1727,14 @@ ST_FUNC void gen_cvt_ftoi(int t) · 14 unmodified lines
1716 }1727 }
1717 else {1728 else {
1718 int d, n = fltr(gv(RC_FLOAT));1729 int d, n = fltr(gv(RC_FLOAT));
1719 int l = ((vtop->type.t & VT_BTYPE) != VT_FLOAT);1730 uint32_t l = ((vtop->type.t & VT_BTYPE) != VT_FLOAT);
1720 --vtop;1731 --vtop;
1721 d = get_reg(RC_INT);1732 d = get_reg(RC_INT);
1722 ++vtop;1733 ++vtop;
1723 vtop[0].r = d;1734 vtop[0].r = d;
1724 o(0x1e380000 |1735 o(0x1e380000 |
1725 !!(t & VT_UNSIGNED) << 16 |1736 (uint32_t)!!(t & VT_UNSIGNED) << 16 |
1726 ((t & VT_BTYPE) == VT_LLONG) << 31 | intr(d) |1737 (uint32_t)((t & VT_BTYPE) == VT_LLONG) << 31 | intr(d) |
1727 l << 22 | n << 5); // fcvtz[su] [wx](d),[sd](n)1738 l << 22 | n << 5); // fcvtz[su] [wx](d),[sd](n)
1728 }1739 }
1729}1740}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t