# Rules for optimizing BCC assembler output # Rules for loading short variables mov %2,%[ax|bx|cx|dx]1 mov %[ax|bx|cx|dx]1,%2 = mov %2,%1 # Assign a constant mov %[ax|bx|cx|dx]3,%[#|*]0%1 mov %2[%4],%[ax|bx|cx|dx]3 !BCC_EOS = mov word ptr %2[%4],%0%1 !BCC_EOS # Assign a constant char mov al,%[#|*]0%1 mov %2,al !BCC_EOS = mov byte ptr %2,%0%1 !BCC_EOS # Assign a constant long from a small int xor ax,ax mov bx,%[#|*]0%1 mov [%2],ax mov [%2+2],bx !BCC_EOS = mov word ptr [%2],#0 mov word ptr [%2+2],%0%1 !BCC_EOS # Assign a constant long from a 2^16 mod int. mov ax,%[#|*]0%1 xor bx,bx mov [%2],ax mov [%2+2],bx !BCC_EOS = mov word ptr [%2],%0%1 mov word ptr [%2+2],#0 !BCC_EOS # Assign a constant long from a big int mov ax,%[#|*]4%1 mov bx,%[#|*]5%3 mov [%2],ax mov [%2+2],bx !BCC_EOS = mov word ptr [%2],%4%1 mov word ptr [%2+2],%5%3 !BCC_EOS # rule for (char*) *x++ mov bx,%1 %[inc|dec]2 bx mov %1,bx mov al,-1[bx] xor ah,ah = mov bx,%1 %2 word ptr %1 mov al,[bx] xor ah,ah # Rules for incrementing short variables mov %[ax|bx|si|di]2,%1 %[inc|dec]3 %[ax|bx|si|di]2 mov %1,%[ax|bx|si|di]2 !BCC_EOS = %3 word ptr %1 !BCC_EOS mov %[ax|bx|si|di]2,%1 %[inc|dec]3 %[ax|bx|si|di]2 mov %1,%[ax|bx|si|di]2 = %3 word ptr %1 mov %2,%1 # Rules for manipulating characters with register char*s inc %[si|di]* inc %[si|di]* mov al,-1[si] mov -1[di],al !BCC_EOS = lodsb stosb !BCC_EOS inc %[si|di]* inc %[si|di]* mov al,-1[di] mov -1[si],al !BCC_EOS = xchg si,di lodsb stosb xchg si,di !BCC_EOS inc si mov al,-1[si] = lodsb inc di mov -1[di],al = stosb dec %[si|di]* dec %[si|di]* mov al,1[si] mov 1[di],al = std lodsb stosb cld dec %[si|di]* dec %[si|di]* mov al,1[di] mov 1[si],al = std xchg si,di lodsb stosb xchg si,di cld dec si mov al,1[si] = std lodsb cld dec di mov 1[di],al = std stosb cld # Rules for manipulating short values # These rules only apply at end of statment. mov %[ax|bx]2,%1 %[add|and|xor|sub|or]4 %[ax|bx]2,%3 mov %1,%[ax|bx]2 !BCC_EOS = mov %2,%3 %4 %1,%2 !BCC_EOS mov %[ax|bx]2,%1 %[add|and|xor|or]4 %[ax|bx]2,%3 mov %3,%[ax|bx]2 !BCC_EOS = mov %2,%1 %4 %3,%2 !BCC_EOS mov al,%1 xor ah,ah %[add|and|xor|sub|or]2 ax,%[#|*]0%3 mov %1,al !BCC_EOS = %2 byte ptr %1,%0%3 !BCC_EOS # This is safe with an embedded assign. mov %[ax|bx]4,%1 %[add|and|xor|sub|or]2 %[si|di]3,%[ax|bx]4 = %2 %3,%1 # Rules for comparing short values # Compare doesn't need to leave any register in a specific state. mov %[ax|bx]3,%1[%4] cmp %[ax|bx]3,%[#|*]0%2 = cmp word ptr %1[%4],%0%2 mov al,%1[%4] cmp al,%[#|*]0%2 = cmp byte ptr %1[%4],%0%2 mov %[ax|bx]3,%[ax|bx|cx|dx|si|di]2 cmp %[ax|bx]3,%1 = cmp %2,%1 # General comparison rules xor %1,%1 mov %2,%3 cmp %2,%1 = mov %2,%3 cmp %2,#0 mov %1,%[#|*]0%2 mov %3,%4 cmp %3,%1 = mov %3,%4 cmp %3,%0%2 mov %1,%2 cmp %1,%[#|*]00 %[jne |je ]4 %3 = mov %1,%2 test %1,%1 %4 %3 %[and|xor|or]1 %2,%3 test %2,%2 = %1 %2,%3 # General incrementation and decrementation rules inc %3 ptr %1 mov %2,%1 dec %2 = mov %2,%1 inc %3 ptr %1 dec %3 ptr %1 mov %2,%1 inc %2 = mov %2,%1 dec %3 ptr %1 mov %1,%2 inc %3 ptr %2 push %1 = push %3 ptr %2 inc %3 ptr %2 mov %1,%2 dec %3 ptr %2 push %1 = push %3 ptr %2 dec %3 ptr %2 # Misc. rules push word %[#|*]0%1 inc %[si|di]2 inc %[si|di]2 mov %[ax|bx|cx|dx]3,%*[bp] mov %4[%[si|di]2],%[ax|bx|cx|dx]3 inc sp inc sp = mov word ptr %(%4+2)[%2],%0%1 inc %2 inc %2 push %1 mov %[ax|bx|cx|dx]3,%2 %[add|and|xor|or]4 %[ax|bx|cx|dx]3,%*[bp] inc sp inc sp = mov %3,%1 %4 %3,%2 # If %1 is ax this fails badly. # push %1 # mov %[ax|bx|cx|dx]3,%2 # %[add|sub|and|xor|or]5 %[ax|bx|cx|dx]3,%6 # %[add|sub|and|xor|or]4 %[ax|dx|cx|dx]3,%*[bp] # inc sp # inc sp # = # mov %3,%2 # %5 %3,%6 # %4 %3,%1 push %1 mov %[ax|bx|cx|dx]3,%*[bp] %[add|sub|and|xor|or]4 %2,%[ax|bx|cx|dx]3 inc sp inc sp = mov %3,%1 %4 %2,%3 mov %1,%[ax|bx|cx|dx]2 push %1 = mov %1,%2 push %2 # Rules to remove superflous mov instructions mov %1,%2 mov %1,%2 = mov %1,%2 mov %1,%2 .%3: mov %1,%2 = .%3: mov %1,%2 mov %1,%2 mov %2,%1 = mov %1,%2 mov %1,%[ax|bx|cx|dx|eax|ebx|ecx|edx]2 mov %[ax|bx|cx|dx|eax|ebx|ecx|edx]3,%1 = mov %1,%2 mov %3,%2 mov %1,%1 = # poof # Sometimes the compiler puts a jump right after a ret or another jump # (in if-else-if constructions). Eliminate the second unnecessary jump. # Also it puts a jump to the next instruction in extensive if-else # constructions. That jump can also be removed. jmp .%1 jmp .%2 = jmp .%1 ret jmp %2 = ret jmp .%1 .%1: = .%1: jmp .%1 .%2: !BCC_EOS .%1: = .%2: !BCC_EOS .%1: jmp .%1 .%3: .%2: .%1: = .%3: .%2: .%1: # When using register variables the compiler initializes them when # they are found in the source code, and sets up the stack frame for # other local variables lateron. Move initialization of register variables # behind the add-sp instruction to make further optimization easier. proc_start mov %[si|di]3,%1 add sp,*%2 = proc_start add sp,*%2 mov %3,%1 proc_start mov %[si|di]3,%1 dec sp dec sp = proc_start dec sp dec sp mov %3,%1 add sp,*%1 add sp,*%2 = add sp,*%1+%2 dec sp dec sp add sp,*%1 = add sp,*%1-2 add sp,*%1 dec sp dec sp = add sp,*%1-2 inc sp inc sp %1 %2 inc sp inc sp = %1 %2 add sp,*4 inc sp inc sp %1 %2 add sp,*%3 = %1 %2 add sp,*%3+2 add sp,*%3 %1 %2 inc sp inc sp = %1 %2 add sp,*%3+2 add sp,*%3 %1 %2 add sp,*%4 = %1 %2 add sp,*%3+%4 # And a great bug floating push/pop push dx push cx push bx push ax pop ax pop bx pop cx pop dx = # poof # Long right shift by 16 unsigned mov ax,%1 mov bx,%2 xchg bx,ax xor bx,bx = mov ax,%2 xor bx,bx # Long right shift by 16 signed mov ax,%1 mov bx,%2 xchg bx,ax cwd = mov ax,%2 cwd # Load long and exchange mov ax,%1 mov bx,%2 xchg bx,ax = mov bx,%1 mov ax,%2 # Repeated clear. xor bx,bx xchg bx,ax xor ax,ax = xchg bx,ax xor ax,ax # Long expression assigned to an int cwd mov bx,dx mov %1,ax !BCC_EOS = mov %1,ax !BCC_EOS # Load unsigned into high word of long mov ax,%1 xchg bx,ax xor ax,ax = mov bx,%1 xor ax,ax # Souped up strcpy; "while(*d++ = *s++);" in a function with no reg vars. .%3: !BCC_EOS .%4: mov bx,%1 inc bx mov %1,bx mov si,%2 inc si mov %2,si mov al,-1[bx] mov -1[si],al test al,al jne .%3 = .%4: mov si,%1 mov di,%2 .%3: lodsb stosb test al,al jne .%3 mov %1,si mov %2,di !BCC_EOS ### mov ax,%1 mov %[ax|bx|cx|dx]2,ax mov ax,%3 = mov %2,%1 mov ax,%3