GNU Binutils with patches for OS216
Révision | 1089f319d74cf1ca7ecefa1c81d32fff3044554f (tree) |
---|---|
l'heure | 2006-06-08 16:23:04 |
Auteur | Nathan Sidwell <nathan@code...> |
Commiter | Nathan Sidwell |
* gdb/m68k-tdep.c (m68k_svr4_extract_return_value): Use
tdep->ptr_value_regnum for pointer returns.
(m68k_svr4_store_return_value): Likewise.
(m68k_reg_struct_return_r): New, broken out of ...
(m68k_reg_struct_return_p): ... here. Implement gcc's structure
mode algorithm.
(m68k_svr4_init_abi, m68k_aout_init_abi): Set ptr_value_regnum.
(m68k_gdbarch_init): Likewise.
* gdb/m68k-tdep.h (struct gdbarch_tdep): Add ptr_value_regnum
field.
@@ -1,3 +1,16 @@ | ||
1 | +2006-06-08 Nathan Sidwell <nathan@codesourcery.com> | |
2 | + | |
3 | + * gdb/m68k-tdep.c (m68k_svr4_extract_return_value): Use | |
4 | + tdep->ptr_value_regnum for pointer returns. | |
5 | + (m68k_svr4_store_return_value): Likewise. | |
6 | + (m68k_reg_struct_return_r): New, broken out of ... | |
7 | + (m68k_reg_struct_return_p): ... here. Implement gcc's structure | |
8 | + mode algorithm. | |
9 | + (m68k_svr4_init_abi, m68k_aout_init_abi): Set ptr_value_regnum. | |
10 | + (m68k_gdbarch_init): Likewise. | |
11 | + * gdb/m68k-tdep.h (struct gdbarch_tdep): Add ptr_value_regnum | |
12 | + field. | |
13 | + | |
1 | 14 | 2006-06-05 Nathan Sidwell <nathan@codesourcery.com> |
2 | 15 | |
3 | 16 | * gdb/remote.c (remote_insert_watchpoint): Return -1, rather than |
@@ -265,11 +265,10 @@ m68k_svr4_extract_return_value (struct type *type, struct regcache *regcache, | ||
265 | 265 | regcache_raw_read (regcache, M68K_FP0_REGNUM, buf); |
266 | 266 | convert_typed_floating (buf, *tdep->fpreg_type, valbuf, type); |
267 | 267 | } |
268 | -#if 0 | |
269 | - /* GCC never differentiates pointer return types this way. */ | |
270 | 268 | else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4) |
271 | - regcache_raw_read (regcache, M68K_A0_REGNUM, valbuf); | |
272 | -#endif | |
269 | + regcache_raw_read (regcache, | |
270 | + gdbarch_tdep (current_gdbarch)->ptr_value_regnum, | |
271 | + valbuf); | |
273 | 272 | else |
274 | 273 | m68k_extract_return_value (type, regcache, valbuf); |
275 | 274 | } |
@@ -309,48 +308,46 @@ m68k_svr4_store_return_value (struct type *type, struct regcache *regcache, | ||
309 | 308 | regcache_raw_write (regcache, M68K_FP0_REGNUM, buf); |
310 | 309 | } |
311 | 310 | else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4) |
312 | - { | |
313 | - regcache_raw_write (regcache, M68K_A0_REGNUM, valbuf); | |
314 | - regcache_raw_write (regcache, M68K_D0_REGNUM, valbuf); | |
315 | - } | |
311 | + regcache_raw_write (regcache, | |
312 | + gdbarch_tdep (current_gdbarch)->ptr_value_regnum, | |
313 | + valbuf); | |
316 | 314 | else |
317 | 315 | m68k_store_return_value (type, regcache, valbuf); |
318 | 316 | } |
319 | 317 | |
320 | 318 | /* Return non-zero if TYPE, which is assumed to be a structure or |
321 | 319 | union type, should be returned in registers for architecture |
322 | - GDBARCH. */ | |
320 | + GDBARCH. | |
321 | + | |
322 | + Unfortunately GCC incorrectly implements this optimization. Rather | |
323 | + than simply return all small structs, or even just those of size | |
324 | + 2^N, it uses the mode of the structure to determine this. BLKmode | |
325 | + structs will be returned by memory and QI,HI,SI,DI,SF&DF mode | |
326 | + structs will be returned by register. For m68k a struct is BLKmode | |
327 | + unless it's size is 2^N and the mode for that size does not need a | |
328 | + greater alignment than the structure itself. This is horrible. */ | |
329 | + | |
323 | 330 | |
324 | 331 | static int |
325 | -m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) | |
332 | +m68k_reg_struct_return_r (struct type *type, int *align_p) | |
326 | 333 | { |
327 | - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
328 | 334 | enum type_code code = TYPE_CODE (type); |
329 | 335 | int len = TYPE_LENGTH (type); |
330 | - int align; | |
336 | + int field_align = 1; | |
337 | + int my_align = len > 2 ? 2 : len; | |
331 | 338 | int ix; |
332 | - struct type *union_field_type = NULL; | |
333 | - | |
334 | - gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION); | |
335 | - | |
336 | - if (tdep->struct_return == pcc_struct_return) | |
337 | - return 0; | |
338 | - | |
339 | - /* Unfortunately GCC incorrectly implements this optimization. | |
340 | - Rather than simply return all small structs, or even just those | |
341 | - of size 2^N, it uses the mode of the structure to determine this. | |
342 | - BLKmode structs will be returned by memory and QI,HI,SI,DI,SF&DF | |
343 | - mode structs will be returned by register. For m68k a struct is | |
344 | - BLKmode unless it's size is 2^N and the mode for that size does | |
345 | - not need a greater alignment than the structure itself. Unions | |
346 | - will get the mode of last member whose size matches that of the | |
347 | - union itself. This is horrible. */ | |
348 | 339 | |
349 | - if (len > 8 || (len & -len) != len) | |
350 | - /* Length is not 2^n or is too big. */ | |
340 | + if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION) | |
341 | + { | |
342 | + if (align_p && my_align > *align_p) | |
343 | + *align_p = my_align; | |
344 | + return 1; | |
345 | + } | |
346 | + | |
347 | + if ((len & -len) != len) | |
348 | + /* Length is not 2^n. */ | |
351 | 349 | return 0; |
352 | 350 | |
353 | - align = len > 4 ? 4 : len; | |
354 | 351 | for (ix = 0; ix != TYPE_NFIELDS (type); ix++) |
355 | 352 | { |
356 | 353 | struct type *field_type; |
@@ -364,60 +361,48 @@ m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) | ||
364 | 361 | field_type = check_typedef (field_type); |
365 | 362 | field_len = TYPE_LENGTH (field_type); |
366 | 363 | |
367 | - if (code == TYPE_CODE_STRUCT) | |
368 | - { | |
369 | - /* Look through arrays. */ | |
370 | - while (TYPE_CODE (field_type) == TYPE_CODE_ARRAY) | |
371 | - { | |
372 | - field_type = TYPE_TARGET_TYPE (field_type); | |
373 | - field_type = check_typedef (field_type); | |
374 | - field_len = TYPE_LENGTH (field_type); | |
375 | - } | |
376 | - | |
377 | - /* If the field's alignment is finer than the structs, we | |
378 | - won't be in registers. */ | |
379 | - if (field_len < align) | |
380 | - return 0; | |
381 | - | |
382 | - /* If the field itself is a struct or union, then check it | |
383 | - can be passed in registers. */ | |
384 | - if ((TYPE_CODE (field_type) == TYPE_CODE_STRUCT | |
385 | - || TYPE_CODE (field_type) == TYPE_CODE_UNION) | |
386 | - && !m68k_reg_struct_return_p (gdbarch, field_type)) | |
387 | - return 0; | |
388 | - } | |
389 | - else | |
364 | + /* Look through arrays. */ | |
365 | + while (TYPE_CODE (field_type) == TYPE_CODE_ARRAY) | |
390 | 366 | { |
391 | - /* If this field accounts for the whole union, remember it. | |
392 | - Note that we remember the last such field to match GCC's | |
393 | - algorithm. */ | |
394 | - if (field_len == len) | |
395 | - union_field_type = field_type; | |
367 | + field_type = TYPE_TARGET_TYPE (field_type); | |
368 | + field_type = check_typedef (field_type); | |
369 | + field_len = TYPE_LENGTH (field_type); | |
396 | 370 | } |
397 | - } | |
398 | 371 | |
399 | - if (code == TYPE_CODE_UNION) | |
400 | - { | |
401 | - if (!union_field_type) | |
372 | + if (!m68k_reg_struct_return_r (field_type, &field_align)) | |
402 | 373 | return 0; |
403 | - /* Look through arrays. */ | |
404 | - while (TYPE_CODE (union_field_type) == TYPE_CODE_ARRAY) | |
405 | - { | |
406 | - union_field_type = TYPE_TARGET_TYPE (union_field_type); | |
407 | - union_field_type = check_typedef (union_field_type); | |
408 | - } | |
409 | - /* If this field's alignment is too small, then we won't be in | |
410 | - registers. */ | |
411 | - if (TYPE_LENGTH (union_field_type) < align) | |
412 | - return 0; | |
413 | - | |
414 | - if (TYPE_CODE (union_field_type) == TYPE_CODE_STRUCT | |
415 | - || TYPE_CODE (union_field_type) == TYPE_CODE_UNION) | |
416 | - return m68k_reg_struct_return_p (gdbarch, union_field_type); | |
417 | 374 | } |
375 | + | |
376 | + if (align_p && field_align > *align_p) | |
377 | + *align_p = field_align; | |
418 | 378 | |
419 | - /* It will be returned in registers */ | |
420 | - return 1; | |
379 | + return align_p || my_align <= field_align; | |
380 | +} | |
381 | + | |
382 | +/* Return non-zero if TYPE, which is assumed to be a structure or | |
383 | + union type, should be returned in registers for architecture | |
384 | + GDBARCH. */ | |
385 | + | |
386 | +static int | |
387 | +m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) | |
388 | +{ | |
389 | + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
390 | + enum type_code code = TYPE_CODE (type); | |
391 | + int len = TYPE_LENGTH (type); | |
392 | + int align; | |
393 | + int ix; | |
394 | + struct type *union_field_type = NULL; | |
395 | + | |
396 | + gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION); | |
397 | + | |
398 | + if (tdep->struct_return == pcc_struct_return) | |
399 | + return 0; | |
400 | + | |
401 | + if (len > 8) | |
402 | + /* Length is too big. */ | |
403 | + return 0; | |
404 | + | |
405 | + return m68k_reg_struct_return_r (type, NULL); | |
421 | 406 | } |
422 | 407 | |
423 | 408 | /* Determine, for architecture GDBARCH, how a return value of TYPE |
@@ -1217,6 +1202,8 @@ m68k_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | ||
1217 | 1202 | /* SVR4 uses %a0. */ |
1218 | 1203 | tdep->struct_value_regnum = M68K_A0_REGNUM; |
1219 | 1204 | tdep->struct_return = reg_struct_return; |
1205 | + /* Pointers are returned in %a0 */ | |
1206 | + tdep->ptr_value_regnum = M68K_A0_REGNUM; | |
1220 | 1207 | } |
1221 | 1208 | |
1222 | 1209 | /* a.out */ |
@@ -1228,8 +1215,11 @@ m68k_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | ||
1228 | 1215 | |
1229 | 1216 | set_gdbarch_return_value (gdbarch, m68k_return_value); |
1230 | 1217 | |
1218 | + /* aout uses %a1 */ | |
1231 | 1219 | tdep->struct_value_regnum = M68K_A1_REGNUM; |
1232 | 1220 | tdep->struct_return = reg_struct_return; |
1221 | + /* Pointers are returned in %a0 */ | |
1222 | + tdep->ptr_value_regnum = M68K_A0_REGNUM; | |
1233 | 1223 | } |
1234 | 1224 | |
1235 | 1225 |
@@ -1286,6 +1276,7 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
1286 | 1276 | set_gdbarch_return_value (gdbarch, m68k_svr4_return_value); |
1287 | 1277 | tdep->struct_value_regnum = M68K_A0_REGNUM; |
1288 | 1278 | tdep->struct_return = reg_struct_return; |
1279 | + tdep->ptr_value_regnum = M68K_D0_REGNUM; | |
1289 | 1280 | tdep->float_return = M68K_RETURN_FP0; |
1290 | 1281 | tdep->fpreg_type = &M68K_FPREG_TYPE; |
1291 | 1282 |
@@ -77,6 +77,9 @@ struct gdbarch_tdep | ||
77 | 77 | /* Convention for returning structures. */ |
78 | 78 | enum struct_return struct_return; |
79 | 79 | |
80 | + /* Register in which pointers are returned. */ | |
81 | + int ptr_value_regnum; | |
82 | + | |
80 | 83 | /* Convention for returning floats. zero in int regs, non-zero in float. */ |
81 | 84 | int float_return; |
82 | 85 |