| @@ -592,6 +592,31 @@ static void gcall_or_jmp(int is_jmp) · 591 unmodified lines |
| 592 | 592 | } |
| 593 | 593 | } |
| 594 | 594 | |
| 595 | +void struct_copy(SValue *d, SValue *s, SValue *c) |
| 596 | +{ |
| 597 | + if(!c->c.i) |
| 598 | + return; |
| 599 | + save_reg(TREG_RCX); |
| 600 | + load(TREG_RCX, c); |
| 601 | + load(TREG_RDI, d); |
| 602 | + load(TREG_RSI, s); |
| 603 | + o(0xa4f3);// rep movsb |
| 604 | +} |
| 605 | + |
| 606 | +void gen_putz(SValue *d, int size) |
| 607 | +{ |
| 608 | + if(!size) |
| 609 | + return; |
| 610 | + save_reg(TREG_RAX); |
| 611 | + o(0xb0); |
| 612 | + g(0x00); |
| 613 | + save_reg(TREG_RCX); |
| 614 | + o(0xb8 + REG_VALUE(TREG_RCX)); /* mov $xx, r */ |
| 615 | + gen_le32(size); |
| 616 | + load(TREG_RDI, d); |
| 617 | + o(0xaaf3);//rep stos |
| 618 | +} |
| 619 | + |
| 595 | 620 | #ifdef TCC_TARGET_PE |
| 596 | 621 | |
| 597 | 622 | #define REGN 4 |
| @@ -1060,14 +1085,6 @@ static const uint8_t arg_regs[REGN] = { · 462 unmodified lines |
| 1060 | 1085 | TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9 |
| 1061 | 1086 | }; |
| 1062 | 1087 | |
| 1063 | | −static int arg_prepare_reg(int idx) { |
| 1064 | | − if (idx == 2 || idx == 3) |
| 1065 | | − /* idx=2: r10, idx=3: r11 */ |
| 1066 | | − return idx + 8; |
| 1067 | | − else |
| 1068 | | − return arg_regs[idx]; |
| 1069 | | −} |
| 1070 | | − |
| 1071 | 1088 | /* Generate function call. The function address is pushed first, then |
| 1072 | 1089 | all the parameters in call order. This functions pops all the |
| 1073 | 1090 | parameters and the function address. */ |
| @@ -1080,6 +1097,9 @@ void gfunc_call(int nb_args) · 6 unmodified lines |
| 1080 | 1097 | int nb_sse_args = 0; |
| 1081 | 1098 | int sse_reg, gen_reg; |
| 1082 | 1099 | |
| 1100 | + /* fetch cpu flag before the following sub will change the value */ |
| 1101 | + if (vtop >= vstack && (vtop->r & VT_VALMASK) == VT_CMP) |
| 1102 | + gv(RC_INT); |
| 1083 | 1103 | /* calculate the number of integer/float register arguments */ |
| 1084 | 1104 | for(i = 0; i < nb_args; i++) { |
| 1085 | 1105 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| @@ -1276,7 +1296,7 @@ void gfunc_call(int nb_args) · 190 unmodified lines |
| 1276 | 1296 | } |
| 1277 | 1297 | |
| 1278 | 1298 | /* XXX This should be superfluous. */ |
| 1279 | | − save_regs(0); /* save used temporary registers */ |
| 1299 | + // save_regs(0); /* save used temporary registers */ |
| 1280 | 1300 | |
| 1281 | 1301 | /* then, we prepare register passing arguments. |
| 1282 | 1302 | Note that we cannot set RDX and RCX in this loop because gv() |
| @@ -1289,36 +1309,34 @@ void gfunc_call(int nb_args) · 6 unmodified lines |
| 1289 | 1309 | /* Alter stack entry type so that gv() knows how to treat it */ |
| 1290 | 1310 | vtop->type = type; |
| 1291 | 1311 | if (mode == x86_64_mode_sse) { |
| 1292 | | − if (reg_count == 2) { |
| 1293 | | − sse_reg -= 2; |
| 1294 | | − gv(RC_FRET); /* Use pair load into xmm0 & xmm1 */ |
| 1295 | | − if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */ |
| 1296 | | − /* movaps %xmm0, %xmmN */ |
| 1297 | | − o(0x280f); |
| 1298 | | − o(0xc0 + (sse_reg << 3)); |
| 1299 | | − /* movaps %xmm1, %xmmN */ |
| 1300 | | − o(0x280f); |
| 1301 | | − o(0xc1 + ((sse_reg+1) << 3)); |
| 1302 | | − } |
| 1303 | | − } else { |
| 1304 | | − assert(reg_count == 1); |
| 1305 | | − --sse_reg; |
| 1306 | | − /* Load directly to register */ |
| 1307 | | − gv(RC_XMM0 << sse_reg); |
| 1308 | | − } |
| 1312 | + sse_reg -= reg_count; |
| 1313 | + if (sse_reg + reg_count <= 8) { |
| 1314 | + if (reg_count == 2) { |
| 1315 | + ex_rc = RC_XMM0 << (sse_reg + 1); |
| 1316 | + gv(RC_XMM0 << sse_reg); |
| 1317 | + }else{ |
| 1318 | + assert(reg_count == 1); |
| 1319 | + /* Load directly to register */ |
| 1320 | + gv(RC_XMM0 << sse_reg); |
| 1321 | + } |
| 1322 | + } |
| 1309 | 1323 | } else if (mode == x86_64_mode_integer) { |
| 1310 | 1324 | /* simple type */ |
| 1311 | 1325 | /* XXX: implicit cast ? */ |
| 1326 | + int d; |
| 1312 | 1327 | gen_reg -= reg_count; |
| 1313 | | − r = gv(RC_INT); |
| 1314 | | − int d = arg_prepare_reg(gen_reg); |
| 1315 | | − orex(1,d,r,0x89); /* mov */ |
| 1316 | | − o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d)); |
| 1317 | | − if (reg_count == 2) { |
| 1318 | | − d = arg_prepare_reg(gen_reg+1); |
| 1319 | | − orex(1,d,vtop->r2,0x89); /* mov */ |
| 1320 | | − o(0xc0 + REG_VALUE(vtop->r2) * 8 + REG_VALUE(d)); |
| 1321 | | − } |
| 1328 | + if (gen_reg + reg_count <= REGN) { |
| 1329 | + if (reg_count == 2) { |
| 1330 | + d = arg_regs[gen_reg+1]; |
| 1331 | + ex_rc = reg_classes[d] & ~RC_MASK; |
| 1332 | + d = arg_regs[gen_reg]; |
| 1333 | + gv(reg_classes[d] & ~RC_MASK); |
| 1334 | + }else{ |
| 1335 | + assert(reg_count == 1); |
| 1336 | + d = arg_regs[gen_reg]; |
| 1337 | + gv(reg_classes[d] & ~RC_MASK); |
| 1338 | + } |
| 1339 | + } |
| 1322 | 1340 | } |
| 1323 | 1341 | vtop--; |
| 1324 | 1342 | } |
| @@ -1330,15 +1348,6 @@ void gfunc_call(int nb_args) · 5 unmodified lines |
| 1330 | 1348 | (or edx/ecx) currently, which the below writes would clobber. |
| 1331 | 1349 | So evict all remaining operands here. */ |
| 1332 | 1350 | save_regs(0); |
| 1333 | | − |
| 1334 | | − /* Copy R10 and R11 into RDX and RCX, respectively */ |
| 1335 | | − if (nb_reg_args > 2) { |
| 1336 | | − o(0xd2894c); /* mov %r10, %rdx */ |
| 1337 | | − if (nb_reg_args > 3) { |
| 1338 | | − o(0xd9894c); /* mov %r11, %rcx */ |
| 1339 | | − } |
| 1340 | | − } |
| 1341 | | − |
| 1342 | 1351 | oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ |
| 1343 | 1352 | gcall_or_jmp(0); |
| 1344 | 1353 | if (args_size) |