Поставил я все 3 компилера.
Для начала решил посуммировать вектора.
Т.к. у ядра всего 2 индексных регистра, интересно посомтреть что будут делать компиляторы, когда их нужно больше.
Код
void add8_2(unsigned char *a, unsigned char *b, unsigned char *c, unsigned char len)
{
do {
*c++ = *a++ + *b++;
} while(--len);
}
Космик использовал только один индексный регистр, по очереди для 3 указателей. Лучше всего скомпилировал while(--len);
Код
43 0016 89 pushw x
44 00000000 OFST: set 0
46 0017 L11:
47 ; 16 *c++ = *a++ + *b++;
48 0017 1e05 ldw x,(OFST+5,sp)
49 0019 f6 ld a,(x)
50 001a 5c incw x
51 001b 1f05 ldw (OFST+5,sp),x
52 001d 1e01 ldw x,(OFST+1,sp)
53 001f fb add a,(x)
54 0020 5c incw x
55 0021 1f01 ldw (OFST+1,sp),x
56 0023 1e07 ldw x,(OFST+7,sp)
57 0025 f7 ld (x),a
58 0026 5c incw x
59 0027 1f07 ldw (OFST+7,sp),x
60 ; 17 } while(--len);
61 0029 0a09 dec (OFST+9,sp)
62 002b 26ea jrne L11
63 ; 18 }
64 002d 85 popw x
65 002e 81 ret
Райзонанс мог бы выйграть - использовал X для *a и Y для *b и *с, но с *a++ у него вышел прокол, поэтому в итоге код получился не лучше. И лишняя проверка после dec
Код
; FUNCTION ?add8_2 (BEGIN)
; Register XW is assigned to parameter a
0000 ?DO_0003:
; SOURCE LINE # 16
0000 1603 F LDW Y,(003H,SP) ; [ b ]
0002 90F6 LD A,(Y)
0004 905C INCW Y
0006 1703 F LDW (003H,SP),Y ; [ b ]
0008 BF03 F LDW ?CH.w,X
000A 5C INCW X
000B 92CB00 F ADD A,[?CH.w]
000E 1605 F LDW Y,(005H,SP) ; [ c ]
0010 90BF02 F LDW ?BH.w,Y
0013 905C INCW Y
0015 1705 F LDW (005H,SP),Y ; [ c ]
0017 92C700 F LD [?BH.w],A
001A 0A07 F DEC (007H,SP) ; [ len ]
001C 0D07 F TNZ (007H,SP) ; [ len ]
001E 26E0 JRNE ?DO_0003
0020 81 RET
У IAR код тоже не фонтан! Но главное посмотрите на while(--len)!!!!
К тому же IAR не использует стек, а использует виртуальные регистры. Что IMHO для этого ядра криво! Что IAR делает хорошо - так это общий код выделят в подпрограммы, если нужно по размеру сжать! И у IAR лучший способ передачи параметров!! задействуются все рагистры.
Код
\ add8_2:
\ 000000 BF00 LDW S:?w1, X
\ 000002 93 LDW X, Y
\ 000003 B700 LD S:?b4, A
12 do {
13 *c++ = *a++ + *b++;
\ ??add8_2_0:
\ 000005 F6 LD A, (X)
\ 000006 92CB00 ADD A, [S:?w1.w]
\ 000009 92C700 LD [S:?w0.w], A
\ 00000C 5C INCW X
\ 00000D 90BE00 LDW Y, S:?w1
\ 000010 905C INCW Y
\ 000012 90BF00 LDW S:?w1, Y
\ 000015 90BE00 LDW Y, S:?w0
\ 000018 905C INCW Y
\ 00001A 90BF00 LDW S:?w0, Y
14 } while(--len);
\ 00001D B600 LD A, S:?b4
\ 00001F ABFF ADD A, #0xff
\ 000021 B700 LD S:?b4, A
\ 000023 4F CLR A
\ 000024 B100 CP A, S:?b4
\ 000026 2600 JRNE L:??add8_2_0
15 }
\ 000028 81 RET
Если код функции поменять на
Код
void add8_21(unsigned char *a, unsigned char *b, unsigned char *c, unsigned char len)
{
do {
*c = *a + *b;
++a; ++b; ++c;
} while(--len);
}
То райзонанс генерирует практически идеальный код
Код
; FUNCTION ?add8_21 (BEGIN)
; Register XW is assigned to parameter a
0000 ?DO_0005:
; SOURCE LINE # 23
0000 1603 F LDW Y,(003H,SP) ; [ b ]
0002 90F6 LD A,(Y)
0004 FB ADD A,(X)
0005 1605 F LDW Y,(005H,SP) ; [ c ]
0007 90F7 LD (Y),A
; SOURCE LINE # 24
0009 5C INCW X
000A 1603 F LDW Y,(003H,SP) ; [ b ]
000C 905C INCW Y
000E 1703 F LDW (003H,SP),Y ; [ b ]
0010 1605 F LDW Y,(005H,SP) ; [ c ]
0012 905C INCW Y
0014 1705 F LDW (005H,SP),Y ; [ c ]
0016 0A07 F DEC (007H,SP) ; [ len ]
0018 0D07 F TNZ (007H,SP) ; [ len ]
001A 26E4 JRNE ?DO_0005
001C 81 RET
С более простой задачей
Код
void add8_1(unsigned char *a, unsigned char *b, unsigned char len)
{
do {
*a++ += *b++;
} while(--len);
}
Все справились примерно одинаково неудовлетворительно!
Ее надо записать в таком виде:
Код
void add8_3(unsigned char *a, unsigned char *b, unsigned char len)
{
do {
*a += *b;
++a;
++b;
} while(--len);
}
Тогда IAR и Райзонанс справились гораздо лучше! Только райзонанс зачем что Y каждый раз сохраняет и загружает, а IAR с фирменным } while(--len);
Космик и X и Y перегружает и код не отличается практически от add8_1
райзонанс
Код
; FUNCTION ?add8_3 (BEGIN)
; Register XW is assigned to parameter a
0000 ?DO_0007:
; SOURCE LINE # 31
0000 1603 F LDW Y,(003H,SP) ; [ b ]
0002 F6 LD A,(X)
0003 90FB ADD A,(Y)
0005 F7 LD (X),A
; SOURCE LINE # 32
0006 5C INCW X
; SOURCE LINE # 33
0007 905C INCW Y
0009 1703 F LDW (003H,SP),Y ; [ b ]
000B 0A05 F DEC (005H,SP) ; [ len ]
000D 0D05 F TNZ (005H,SP) ; [ len ]
000F 26EF JRNE ?DO_0007
0011 81 RET
IAR
Код
24 void add8_3(unsigned char *a, unsigned char *b, unsigned char len)
25 {
\ add8_3:
\ 000000 B700 LD S:?b0, A
26 do {
27 *a += *b;
\ ??add8_3_0:
\ 000002 90F6 LD A, (Y)
\ 000004 FB ADD A, (X)
\ 000005 F7 LD (X), A
28 ++a;
\ 000006 5C INCW X
29 ++b;
\ 000007 905C INCW Y
30 } while(--len);
\ 000009 B600 LD A, S:?b0
\ 00000B ABFF ADD A, #0xff
\ 00000D B700 LD S:?b0, A
\ 00000F 4F CLR A
\ 000010 B100 CP A, S:?b0
\ 000012 2600 JRNE L:??add8_3_0
31 }
\ 000014 81 RET
Cosmic
Код
100 004e _add8_3:
101 004e 89 pushw x
102 00000000 OFST: set 0
104 004f L52:
105 ; 32 *a += *b;
106 004f 1e01 ldw x,(OFST+1,sp)
107 0051 1605 ldw y,(OFST+5,sp)
108 0053 f6 ld a,(x)
109 0054 90fb add a,(y)
110 0056 f7 ld (x),a
111 ; 33 ++a;
112 0057 5c incw x
113 0058 1f01 ldw (OFST+1,sp),x
114 ; 34 ++b;
115 005a 1e05 ldw x,(OFST+5,sp)
116 005c 5c incw x
117 005d 1f05 ldw (OFST+5,sp),x
118 ; 35 } while(--len);
119 005f 0a07 dec (OFST+7,sp)
120 0061 26ec jrne L52
121 ; 36 }
122 0063 85 popw x
123 0064 81 ret
В общем надо что то посложнее попробовать!
Цитата(Pat @ Apr 18 2010, 21:28)
Было интересно посмотреть вход в прерывание и не очень проникся там сплошные call.
Это сокрее всего из-за настройки оптимизации - надо вместо Balanced поставить Speed или Cross Call убрать!