| @@ -96,9 +96,9 @@ enum { · 95 unmodified lines |
| 96 | | 96 | |
| 97 | /* long double size and alignment, in bytes */ | 97 | /* long double size and alignment, in bytes */ |
| 98 | #define LDOUBLE_SIZE 16 | 98 | #define LDOUBLE_SIZE 16 |
| 99 | #define LDOUBLE_ALIGN 8 | 99 | #define LDOUBLE_ALIGN 16 |
| 100 | /* maximum alignment (for aligned attribute support) */ | 100 | /* maximum alignment (for aligned attribute support) */ |
| 101 | #define MAX_ALIGN 8 | 101 | #define MAX_ALIGN 16 |
| 102 | | 102 | |
| 103 | /******************************************************/ | 103 | /******************************************************/ |
| 104 | /* ELF defines */ | 104 | /* ELF defines */ |
| @@ -983,7 +983,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { · 878 unmodified lines |
| 983 | assert(0); | 983 | assert(0); |
| 984 | } | 984 | } |
| 985 | | 985 | |
| 986 | static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *reg_count) { | 986 | static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) { |
| 987 | X86_64_Mode mode; | 987 | X86_64_Mode mode; |
| 988 | int size, align, ret_t; | 988 | int size, align, ret_t; |
| 989 | | 989 | |
| @@ -995,6 +995,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *r · 5 unmodified lines |
| 995 | } else { | 995 | } else { |
| 996 | size = type_size(ty, &align); | 996 | size = type_size(ty, &align); |
| 997 | *psize = (size + 7) & ~7; | 997 | *psize = (size + 7) & ~7; |
| | 998 | *palign = (align + 7) & ~7; |
| 998 | | 999 | |
| 999 | if (size > 16) { | 1000 | if (size > 16) { |
| 1000 | mode = x86_64_mode_memory; | 1001 | mode = x86_64_mode_memory; |
| @@ -1042,8 +1043,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { · 41 unmodified lines |
| 1042 | enum __va_arg_type { | 1043 | enum __va_arg_type { |
| 1043 | __va_gen_reg, __va_float_reg, __va_stack | 1044 | __va_gen_reg, __va_float_reg, __va_stack |
| 1044 | }; | 1045 | }; |
| 1045 | int size, reg_count; | 1046 | int size, align, reg_count; |
| 1046 | X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, ®_count); | 1047 | X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count); |
| 1047 | switch (mode) { | 1048 | switch (mode) { |
| 1048 | default: return __va_stack; | 1049 | default: return __va_stack; |
| 1049 | case x86_64_mode_integer: return __va_gen_reg; | 1050 | case x86_64_mode_integer: return __va_gen_reg; |
| @@ -1053,9 +1054,9 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { · 3 unmodified lines |
| 1053 | | 1054 | |
| 1054 | /* Return 1 if this function returns via an sret pointer, 0 otherwise */ | 1055 | /* Return 1 if this function returns via an sret pointer, 0 otherwise */ |
| 1055 | int gfunc_sret(CType *vt, CType *ret, int *ret_align) { | 1056 | int gfunc_sret(CType *vt, CType *ret, int *ret_align) { |
| 1056 | int size, reg_count; | 1057 | int size, align, reg_count; |
| 1057 | *ret_align = 1; // Never have to re-align return values for x86-64 | 1058 | *ret_align = 1; // Never have to re-align return values for x86-64 |
| 1058 | return (classify_x86_64_arg(vt, ret, &size, ®_count) == x86_64_mode_memory); | 1059 | return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) == x86_64_mode_memory); |
| 1059 | } | 1060 | } |
| 1060 | | 1061 | |
| 1061 | #define REGN 6 | 1062 | #define REGN 6 |
| @@ -1078,77 +1079,187 @@ void gfunc_call(int nb_args) · 16 unmodified lines |
| 1078 | { | 1079 | { |
| 1079 | X86_64_Mode mode; | 1080 | X86_64_Mode mode; |
| 1080 | CType type; | 1081 | CType type; |
| 1081 | int size, align, r, args_size, i, j, reg_count; | 1082 | int size, align, r, args_size, stack_adjust, run_start, run_end, i, j, reg_count; |
| 1082 | int nb_reg_args = 0; | 1083 | int nb_reg_args = 0; |
| 1083 | int nb_sse_args = 0; | 1084 | int nb_sse_args = 0; |
| 1084 | int sse_reg, gen_reg; | 1085 | int sse_reg, gen_reg; |
| 1085 | | 1086 | |
| 1086 | /* calculate the number of integer/float arguments */ | 1087 | /* calculate the number of integer/float register arguments */ |
| 1087 | args_size = 0; | | |
| 1088 | for(i = 0; i < nb_args; i++) { | 1088 | for(i = 0; i < nb_args; i++) { |
| 1089 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, ®_count); | 1089 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| 1090 | switch (mode) { | 1090 | if (mode == x86_64_mode_sse) |
| 1091 | case x86_64_mode_memory: | | |
| 1092 | case x86_64_mode_x87: | | |
| 1093 | args_size += size; | | |
| 1094 | break; | | |
| 1095 | | | |
| 1096 | case x86_64_mode_sse: | | |
| 1097 | nb_sse_args += reg_count; | 1091 | nb_sse_args += reg_count; |
| 1098 | if (nb_sse_args > 8) args_size += size; | 1092 | else if (mode == x86_64_mode_integer) |
| 1099 | break; | | |
| 1100 | | | |
| 1101 | case x86_64_mode_integer: | | |
| 1102 | nb_reg_args += reg_count; | 1093 | nb_reg_args += reg_count; |
| 1103 | if (nb_reg_args > REGN) args_size += size; | | |
| 1104 | break; | | |
| 1105 | } | | |
| 1106 | } | 1094 | } |
| 1107 | | 1095 | |
| | 1096 | /* arguments are collected in runs. Each run is a collection of 8-byte aligned arguments |
| | 1097 | and ended by a 16-byte aligned argument. This is because, from the point of view of |
| | 1098 | the callee, argument alignment is computed from the bottom up. */ |
| 1108 | /* for struct arguments, we need to call memcpy and the function | 1099 | /* for struct arguments, we need to call memcpy and the function |
| 1109 | call breaks register passing arguments we are preparing. | 1100 | call breaks register passing arguments we are preparing. |
| 1110 | So, we process arguments which will be passed by stack first. */ | 1101 | So, we process arguments which will be passed by stack first. */ |
| 1111 | gen_reg = nb_reg_args; | 1102 | gen_reg = nb_reg_args; |
| 1112 | sse_reg = nb_sse_args; | 1103 | sse_reg = nb_sse_args; |
| 1113 | | 1104 | run_start = 0; |
| 1114 | /* adjust stack to align SSE boundary */ | 1105 | args_size = 0; |
| 1115 | if (args_size &= 15) { | 1106 | while (run_start != nb_args) { |
| 1116 | /* fetch cpu flag before the following sub will change the value */ | 1107 | int run_gen_reg = gen_reg, run_sse_reg = sse_reg; |
| 1117 | if (vtop >= vstack && (vtop->r & VT_VALMASK) == VT_CMP) | | |
| 1118 | gv(RC_INT); | | |
| 1119 | | | |
| 1120 | args_size = 16 - args_size; | | |
| 1121 | o(0x48); | | |
| 1122 | oad(0xec81, args_size); /* sub $xxx, %rsp */ | | |
| 1123 | } | | |
| 1124 | | | |
| 1125 | for(i = 0; i < nb_args;) { | | |
| 1126 | /* Swap argument to top, it will possibly be changed here, | | |
| 1127 | and might use more temps. At the end of the loop we keep | | |
| 1128 | in on the stack and swap it back to its original position | | |
| 1129 | if it is a register. */ | | |
| 1130 | SValue tmp = vtop[0]; | | |
| 1131 | vtop[0] = vtop[-i]; | | |
| 1132 | vtop[-i] = tmp; | | |
| 1133 | | | |
| 1134 | mode = classify_x86_64_arg(&vtop->type, NULL, &size, ®_count); | | |
| 1135 | | 1108 | |
| 1136 | int arg_stored = 1; | 1109 | run_end = nb_args; |
| 1137 | switch (vtop->type.t & VT_BTYPE) { | 1110 | stack_adjust = 0; |
| 1138 | case VT_STRUCT: | 1111 | for(i = run_start; (i < nb_args) && (run_end == nb_args); i++) { |
| 1139 | if (mode == x86_64_mode_sse) { | 1112 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| 1140 | if (sse_reg > 8) | 1113 | switch (mode) { |
| 1141 | sse_reg -= reg_count; | 1114 | case x86_64_mode_memory: |
| | 1115 | case x86_64_mode_x87: |
| | 1116 | stack_arg: |
| | 1117 | if (align == 16) |
| | 1118 | run_end = i; |
| 1142 | else | 1119 | else |
| | 1120 | stack_adjust += size; |
| | 1121 | break; |
| | 1122 | |
| | 1123 | case x86_64_mode_sse: |
| | 1124 | sse_reg -= reg_count; |
| | 1125 | if (sse_reg + reg_count > 8) goto stack_arg; |
| | 1126 | break; |
| | 1127 | |
| | 1128 | case x86_64_mode_integer: |
| | 1129 | gen_reg -= reg_count; |
| | 1130 | if (gen_reg + reg_count > REGN) goto stack_arg; |
| | 1131 | break; |
| | 1132 | } |
| | 1133 | } |
| | 1134 | |
| | 1135 | gen_reg = run_gen_reg; |
| | 1136 | sse_reg = run_sse_reg; |
| | 1137 | |
| | 1138 | /* adjust stack to align SSE boundary */ |
| | 1139 | if (stack_adjust &= 15) { |
| | 1140 | /* fetch cpu flag before the following sub will change the value */ |
| | 1141 | if (vtop >= vstack && (vtop->r & VT_VALMASK) == VT_CMP) |
| | 1142 | gv(RC_INT); |
| | 1143 | |
| | 1144 | stack_adjust = 16 - stack_adjust; |
| | 1145 | o(0x48); |
| | 1146 | oad(0xec81, stack_adjust); /* sub $xxx, %rsp */ |
| | 1147 | args_size += stack_adjust; |
| | 1148 | } |
| | 1149 | |
| | 1150 | for(i = run_start; i < run_end;) { |
| | 1151 | /* Swap argument to top, it will possibly be changed here, |
| | 1152 | and might use more temps. At the end of the loop we keep |
| | 1153 | in on the stack and swap it back to its original position |
| | 1154 | if it is a register. */ |
| | 1155 | SValue tmp = vtop[0]; |
| | 1156 | vtop[0] = vtop[-i]; |
| | 1157 | vtop[-i] = tmp; |
| | 1158 | |
| | 1159 | mode = classify_x86_64_arg(&vtop->type, NULL, &size, &align, ®_count); |
| | 1160 | |
| | 1161 | int arg_stored = 1; |
| | 1162 | switch (vtop->type.t & VT_BTYPE) { |
| | 1163 | case VT_STRUCT: |
| | 1164 | if (mode == x86_64_mode_sse) { |
| | 1165 | if (sse_reg > 8) |
| | 1166 | sse_reg -= reg_count; |
| | 1167 | else |
| | 1168 | arg_stored = 0; |
| | 1169 | } else if (mode == x86_64_mode_integer) { |
| | 1170 | if (gen_reg > REGN) |
| | 1171 | gen_reg -= reg_count; |
| | 1172 | else |
| | 1173 | arg_stored = 0; |
| | 1174 | } |
| | 1175 | |
| | 1176 | if (arg_stored) { |
| | 1177 | /* allocate the necessary size on stack */ |
| | 1178 | o(0x48); |
| | 1179 | oad(0xec81, size); /* sub $xxx, %rsp */ |
| | 1180 | /* generate structure store */ |
| | 1181 | r = get_reg(RC_INT); |
| | 1182 | orex(1, r, 0, 0x89); /* mov %rsp, r */ |
| | 1183 | o(0xe0 + REG_VALUE(r)); |
| | 1184 | vset(&vtop->type, r | VT_LVAL, 0); |
| | 1185 | vswap(); |
| | 1186 | vstore(); |
| | 1187 | args_size += size; |
| | 1188 | } |
| | 1189 | break; |
| | 1190 | |
| | 1191 | case VT_LDOUBLE: |
| | 1192 | assert(0); |
| | 1193 | break; |
| | 1194 | |
| | 1195 | case VT_FLOAT: |
| | 1196 | case VT_DOUBLE: |
| | 1197 | assert(mode == x86_64_mode_sse); |
| | 1198 | if (sse_reg > 8) { |
| | 1199 | --sse_reg; |
| | 1200 | r = gv(RC_FLOAT); |
| | 1201 | o(0x50); /* push $rax */ |
| | 1202 | /* movq %xmmN, (%rsp) */ |
| | 1203 | o(0xd60f66); |
| | 1204 | o(0x04 + REG_VALUE(r)*8); |
| | 1205 | o(0x24); |
| | 1206 | args_size += size; |
| | 1207 | } else { |
| 1143 | arg_stored = 0; | 1208 | arg_stored = 0; |
| 1144 | } else if (mode == x86_64_mode_integer) { | 1209 | } |
| 1145 | if (gen_reg > REGN) | 1210 | break; |
| 1146 | gen_reg -= reg_count; | 1211 | |
| 1147 | else | 1212 | default: |
| | 1213 | assert(mode == x86_64_mode_integer); |
| | 1214 | /* simple type */ |
| | 1215 | /* XXX: implicit cast ? */ |
| | 1216 | if (gen_reg > REGN) { |
| | 1217 | --gen_reg; |
| | 1218 | r = gv(RC_INT); |
| | 1219 | orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */ |
| | 1220 | args_size += size; |
| | 1221 | } else { |
| 1148 | arg_stored = 0; | 1222 | arg_stored = 0; |
| | 1223 | } |
| | 1224 | break; |
| 1149 | } | 1225 | } |
| 1150 | | 1226 | |
| | 1227 | /* And swap the argument back to it's original position. */ |
| | 1228 | tmp = vtop[0]; |
| | 1229 | vtop[0] = vtop[-i]; |
| | 1230 | vtop[-i] = tmp; |
| | 1231 | |
| 1151 | if (arg_stored) { | 1232 | if (arg_stored) { |
| | 1233 | vrotb(i+1); |
| | 1234 | assert((vtop->type.t == tmp.type.t) && (vtop->r == tmp.r)); |
| | 1235 | vpop(); |
| | 1236 | --nb_args; |
| | 1237 | --run_end; |
| | 1238 | } else { |
| | 1239 | ++i; |
| | 1240 | } |
| | 1241 | } |
| | 1242 | |
| | 1243 | /* handle 16 byte aligned arguments at end of run */ |
| | 1244 | run_start = i = run_end; |
| | 1245 | while (i < nb_args) { |
| | 1246 | /* Rotate argument to top since it will always be popped */ |
| | 1247 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| | 1248 | if (align != 16) |
| | 1249 | break; |
| | 1250 | |
| | 1251 | vrotb(i+1); |
| | 1252 | |
| | 1253 | if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) { |
| | 1254 | gv(RC_ST0); |
| | 1255 | oad(0xec8148, size); /* sub $xxx, %rsp */ |
| | 1256 | o(0x7cdb); /* fstpt 0(%rsp) */ |
| | 1257 | g(0x24); |
| | 1258 | g(0x00); |
| | 1259 | args_size += size; |
| | 1260 | } else { |
| | 1261 | assert(mode == x86_64_mode_memory); |
| | 1262 | |
| 1152 | /* allocate the necessary size on stack */ | 1263 | /* allocate the necessary size on stack */ |
| 1153 | o(0x48); | 1264 | o(0x48); |
| 1154 | oad(0xec81, size); /* sub $xxx, %rsp */ | 1265 | oad(0xec81, size); /* sub $xxx, %rsp */ |
| @@ -1161,65 +1272,12 @@ void gfunc_call(int nb_args) · 6 unmodified lines |
| 1161 | vstore(); | 1272 | vstore(); |
| 1162 | args_size += size; | 1273 | args_size += size; |
| 1163 | } | 1274 | } |
| 1164 | break; | | |
| 1165 | | 1275 | |
| 1166 | case VT_LDOUBLE: | 1276 | vpop(); |
| 1167 | gv(RC_ST0); | 1277 | --nb_args; |
| 1168 | size = LDOUBLE_SIZE; | | |
| 1169 | oad(0xec8148, size); /* sub $xxx, %rsp */ | | |
| 1170 | o(0x7cdb); /* fstpt 0(%rsp) */ | | |
| 1171 | g(0x24); | | |
| 1172 | g(0x00); | | |
| 1173 | args_size += size; | | |
| 1174 | break; | | |
| 1175 | | | |
| 1176 | case VT_FLOAT: | | |
| 1177 | case VT_DOUBLE: | | |
| 1178 | assert(mode == x86_64_mode_sse); | | |
| 1179 | if (sse_reg > 8) { | | |
| 1180 | --sse_reg; | | |
| 1181 | r = gv(RC_FLOAT); | | |
| 1182 | o(0x50); /* push $rax */ | | |
| 1183 | /* movq %xmmN, (%rsp) */ | | |
| 1184 | o(0xd60f66); | | |
| 1185 | o(0x04 + REG_VALUE(r)*8); | | |
| 1186 | o(0x24); | | |
| 1187 | args_size += size; | | |
| 1188 | } else { | | |
| 1189 | arg_stored = 0; | | |
| 1190 | } | | |
| 1191 | break; | | |
| 1192 | | | |
| 1193 | default: | | |
| 1194 | assert(mode == x86_64_mode_integer); | | |
| 1195 | /* simple type */ | | |
| 1196 | /* XXX: implicit cast ? */ | | |
| 1197 | if (gen_reg > REGN) { | | |
| 1198 | --gen_reg; | | |
| 1199 | r = gv(RC_INT); | | |
| 1200 | orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */ | | |
| 1201 | args_size += size; | | |
| 1202 | } else { | | |
| 1203 | arg_stored = 0; | | |
| 1204 | } | | |
| 1205 | break; | | |
| 1206 | } | | |
| 1207 | | | |
| 1208 | /* And swap the argument back to it's original position. */ | | |
| 1209 | tmp = vtop[0]; | | |
| 1210 | vtop[0] = vtop[-i]; | | |
| 1211 | vtop[-i] = tmp; | | |
| 1212 | | | |
| 1213 | if (arg_stored) { | | |
| 1214 | vrotb(i+1); | | |
| 1215 | assert(vtop->type.t == tmp.type.t); | | |
| 1216 | vpop(); | | |
| 1217 | --nb_args; | | |
| 1218 | } else { | | |
| 1219 | ++i; | | |
| 1220 | } | 1278 | } |
| 1221 | } | 1279 | } |
| 1222 | | 1280 | |
| 1223 | /* XXX This should be superfluous. */ | 1281 | /* XXX This should be superfluous. */ |
| 1224 | save_regs(0); /* save used temporary registers */ | 1282 | save_regs(0); /* save used temporary registers */ |
| 1225 | | 1283 | |
| @@ -1230,7 +1288,7 @@ void gfunc_call(int nb_args) · 4 unmodified lines |
| 1230 | assert(gen_reg <= REGN); | 1288 | assert(gen_reg <= REGN); |
| 1231 | assert(sse_reg <= 8); | 1289 | assert(sse_reg <= 8); |
| 1232 | for(i = 0; i < nb_args; i++) { | 1290 | for(i = 0; i < nb_args; i++) { |
| 1233 | mode = classify_x86_64_arg(&vtop->type, &type, &size, ®_count); | 1291 | mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, ®_count); |
| 1234 | /* Alter stack entry type so that gv() knows how to treat it */ | 1292 | /* Alter stack entry type so that gv() knows how to treat it */ |
| 1235 | vtop->type = type; | 1293 | vtop->type = type; |
| 1236 | if (mode == x86_64_mode_sse) { | 1294 | if (mode == x86_64_mode_sse) { |
| @@ -1324,10 +1382,11 @@ void gfunc_prolog(CType *func_type) · 87 unmodified lines |
| 1324 | sym = func_type->ref; | 1382 | sym = func_type->ref; |
| 1325 | while ((sym = sym->next) != NULL) { | 1383 | while ((sym = sym->next) != NULL) { |
| 1326 | type = &sym->type; | 1384 | type = &sym->type; |
| 1327 | mode = classify_x86_64_arg(type, NULL, &size, ®_count); | 1385 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); |
| 1328 | switch (mode) { | 1386 | switch (mode) { |
| 1329 | default: | 1387 | default: |
| 1330 | seen_stack_size += size; | 1388 | stack_arg: |
| | 1389 | seen_stack_size = ((seen_stack_size + align - 1) & -align) + size; |
| 1331 | break; | 1390 | break; |
| 1332 | | 1391 | |
| 1333 | case x86_64_mode_integer: | 1392 | case x86_64_mode_integer: |
| @@ -1335,7 +1394,7 @@ void gfunc_prolog(CType *func_type) · 1 unmodified line |
| 1335 | seen_reg_num += reg_count; | 1394 | seen_reg_num += reg_count; |
| 1336 | } else { | 1395 | } else { |
| 1337 | seen_reg_num = 8; | 1396 | seen_reg_num = 8; |
| 1338 | seen_stack_size += size; | 1397 | goto stack_arg; |
| 1339 | } | 1398 | } |
| 1340 | break; | 1399 | break; |
| 1341 | | 1400 | |
| @@ -1344,7 +1403,7 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines |
| 1344 | seen_sse_num += reg_count; | 1403 | seen_sse_num += reg_count; |
| 1345 | } else { | 1404 | } else { |
| 1346 | seen_sse_num = 8; | 1405 | seen_sse_num = 8; |
| 1347 | seen_stack_size += size; | 1406 | goto stack_arg; |
| 1348 | } | 1407 | } |
| 1349 | break; | 1408 | break; |
| 1350 | } | 1409 | } |
| @@ -1383,7 +1442,7 @@ void gfunc_prolog(CType *func_type) · 32 unmodified lines |
| 1383 | /* if the function returns a structure, then add an | 1442 | /* if the function returns a structure, then add an |
| 1384 | implicit pointer parameter */ | 1443 | implicit pointer parameter */ |
| 1385 | func_vt = sym->type; | 1444 | func_vt = sym->type; |
| 1386 | mode = classify_x86_64_arg(&func_vt, NULL, &size, ®_count); | 1445 | mode = classify_x86_64_arg(&func_vt, NULL, &size, &align, ®_count); |
| 1387 | if (mode == x86_64_mode_memory) { | 1446 | if (mode == x86_64_mode_memory) { |
| 1388 | push_arg_reg(reg_param_index); | 1447 | push_arg_reg(reg_param_index); |
| 1389 | func_vc = loc; | 1448 | func_vc = loc; |
| @@ -1392,7 +1451,7 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines |
| 1392 | /* define parameters */ | 1451 | /* define parameters */ |
| 1393 | while ((sym = sym->next) != NULL) { | 1452 | while ((sym = sym->next) != NULL) { |
| 1394 | type = &sym->type; | 1453 | type = &sym->type; |
| 1395 | mode = classify_x86_64_arg(type, NULL, &size, ®_count); | 1454 | mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count); |
| 1396 | switch (mode) { | 1455 | switch (mode) { |
| 1397 | case x86_64_mode_sse: | 1456 | case x86_64_mode_sse: |
| 1398 | if (sse_param_index + reg_count <= 8) { | 1457 | if (sse_param_index + reg_count <= 8) { |
| @@ -1405,6 +1464,7 @@ void gfunc_prolog(CType *func_type) · 6 unmodified lines |
| 1405 | ++sse_param_index; | 1464 | ++sse_param_index; |
| 1406 | } | 1465 | } |
| 1407 | } else { | 1466 | } else { |
| | 1467 | addr = (addr + align - 1) & -align; |
| 1408 | param_addr = addr; | 1468 | param_addr = addr; |
| 1409 | addr += size; | 1469 | addr += size; |
| 1410 | sse_param_index += reg_count; | 1470 | sse_param_index += reg_count; |
| @@ -1413,6 +1473,7 @@ void gfunc_prolog(CType *func_type) · 2 unmodified lines |
| 1413 | | 1473 | |
| 1414 | case x86_64_mode_memory: | 1474 | case x86_64_mode_memory: |
| 1415 | case x86_64_mode_x87: | 1475 | case x86_64_mode_x87: |
| | 1476 | addr = (addr + align - 1) & -align; |
| 1416 | param_addr = addr; | 1477 | param_addr = addr; |
| 1417 | addr += size; | 1478 | addr += size; |
| 1418 | break; | 1479 | break; |
| @@ -1427,6 +1488,7 @@ void gfunc_prolog(CType *func_type) · 8 unmodified lines |
| 1427 | ++reg_param_index; | 1488 | ++reg_param_index; |
| 1428 | } | 1489 | } |
| 1429 | } else { | 1490 | } else { |
| | 1491 | addr = (addr + align - 1) & -align; |
| 1430 | param_addr = addr; | 1492 | param_addr = addr; |
| 1431 | addr += size; | 1493 | addr += size; |
| 1432 | reg_param_index += reg_count; | 1494 | reg_param_index += reg_count; |