Воссоздать - убрать весь лишний мусор и оставить баг в чистом виде :-)
Вот:
Код
typedef void *(*fptr_t)( uint);
fptr_t func2( uint Event)
{
return (fptr_t) 0;
}
fptr_t func1( uint Event)
{
switch ( Event)
{
case 1:
nop();
return (fptr_t) 0;
case 5:
return (fptr_t) 0;
case 6:
return (fptr_t) 0;
}
return (fptr_t) func2;
}
//
14312 .global _func2; export
14313 _func2:
14336 000000 00 00 05 retlw #0,w0
//
14359 .global _func1; export
14360 _func1:
14383 000002 E1 0F 50 sub w0,#1,[w15]
14385 000004 00 00 32 bra z,.L7
14387 000006 00 00 31 bra geu,.L13
14388 .L6:
14390 000008 01 00 20 mov #handle(_func2),w1
14392 00000a 00 00 06 return
14393 .L14:
14395 .L13:
14397 00000c 65 00 50 sub w0,#5,w0
14398 00000e 80 00 EB clr w1
14399 000010 E1 0F 50 sub w0,#1,[w15]
14401 000012 00 00 3E bra gtu,.L6
14403 000014 01 00 78 mov w1,w0
14404 000016 00 00 06 return
14405 000018 00 00 37 bra .L14
14406 .L7:
14408 00001a 00 00 00 nop
14409 00001c 00 00 20 mov.w #0,w0
14411 00001e 00 00 06 return
14412 000020 00 00 37 bra .L14
//
Указатель на func2 возвращается в регистре w1 вместо w0 (а в w0 может быть все, что угодно).
Если, скажем, в case 5: добавить nop(), то все корректно (хотя и не оптимально, мягко скажем):
Код
14360 _func1:
14383 000002 E5 0F 50 sub w0,#5,[w15]
14385 000004 00 00 32 bra z,.L8
14386 000006 80 00 EB clr w1
14387 000008 E6 0F 50 sub w0,#6,[w15]
14389 00000a 00 00 32 bra z,.L10
14391 00000c 01 00 20 mov #handle(_func2),w1
14393 00000e E1 0F 50 sub w0,#1,[w15]
14395 000010 00 00 32 bra z,.L14
14396 .L10:
14398 000012 01 00 78 mov w1,w0
14399 000014 00 00 06 return
14400 .L15:
14402 .L8:
14404 000016 00 00 00 nop
14405 000018 00 00 20 mov.w #0,w0
14407 00001a 00 00 06 return
14408 00001c 00 00 37 bra .L15
14409 .L14:
14411 00001e 00 00 00 nop
14412 000020 00 00 20 mov.w #0,w0
14414 000022 00 00 06 return
14415 000024 00 00 37 bra .L15