# Rules for optimizing BCC assembler output # # $Id: rules.86,v 1.3 2003/03/04 19:02:41 gkminix Exp $ # Rules for loading short variables mov %0$0[%2],%3 = mov %0[%2],%3 mov %2,%[ax|bx|cx|dx]1 mov %[ax|bx|cx|dx]1,%2 = mov %2,%1 mov %[ax|bx|cx|dx]3,%[#|*]0%1 mov %2[%4],%[ax|bx|cx|dx]3 = mov word ptr %2[%4],%0%1 mov %[ax|bx|cx|dx]3,%[#|*]0%1 mov %[ax|bx|cx|dx]2,%[ax|bx|cx|dx]3 = mov %2,%0%1 mov al,%[#|*]0%1 mov %2,al = mov byte ptr %2,%0%1 xor ax,ax mov bx,%[#|*]0%1 mov [%2],ax mov [%2+2],bx = mov word ptr [%2],#0 mov word ptr [%2+2],%0%1 mov ax,%[#|*]0%1 xor bx,bx mov [%2],ax mov [%2+2],bx = mov word ptr [%2],%0%1 mov word ptr [%2+2],#0 mov ax,%[#|*]4%1 mov bx,%[#|*]5%3 mov [%2],ax mov [%2+2],bx = mov word ptr [%2],%4%1 mov word ptr [%2+2],%5%3 mov %[ax|bx|cx|dx]1,#%2+%3 sub %[ax|bx|cx|dx]1,%[word #|#]*%2 = mov %1,#%3 mov %[ax|bx|cx|dx]1,%[#|*]2%3 %[add|sub|and|xor|or]6 %4[%5],%[ax|bx|cx|dx]1 = %6 word ptr %4[%5],%2%3 # Rules for incrementing short variables mov %[ax|bx]2,%1 %[inc|dec]3 %[ax|bx]2 mov %1,%[ax|bx]2 = %3 word ptr %1 mov %2,%1 %[inc|dec]1 word ptr %2 mov %[ax|bx|cx|dx]*,%2 .%4: = %1 word ptr %2 .%4: # Rules for manipulating characters inc %[si|di]* inc %[si|di]* mov al,-1[si] mov -1[di],al = cld lodsb stosb inc %[si|di]* inc %[si|di]* mov al,-1[di] mov -1[si],al = cld xchg si,di lodsb stosb xchg si,di inc si mov al,-1[si] = cld lodsb inc di mov -1[di],al = cld stosb dec %[si|di]* dec %[si|di]* mov al,1[si] mov 1[di],al = std lodsb stosb dec %[si|di]* dec %[si|di]* mov al,1[di] mov 1[si],al = std xchg si,di lodsb stosb xchg si,di dec si mov al,1[si] = std lodsb dec di mov 1[di],al = std stosb inc si %[mov|xor]0 al,%1 mov -1[si],al = %0 al,%1 mov [si],al inc si inc word ptr %1 mov bx,%1 mov al,-1[bx] = mov bx,%1 mov al,[bx] inc word ptr %1 # Rules for manipulating short values mov %[ax|bx]2,%1 %[add|and|xor|sub|or]4 %[ax|bx]2,%3 mov %1,%[ax|bx]2 = mov %2,%3 %4 %1,%2 mov %[ax|bx]2,%1 %[add|and|xor|or]4 %[ax|bx]2,%3 mov %3,%[ax|bx]2 = mov %2,%1 %4 %3,%2 mov ax,%1 mov bx,%2 %[add|and|xor|sub|or]4 bx,ax mov %5,bx = mov bx,%2 %4 bx,%1 mov %5,bx mov %[ax|bx]4,%1 %[add|and|xor|sub|or]2 %[si|di]3,%[ax|bx]4 = %2 %3,%1 mov al,%1 xor ah,ah %[add|and|xor|sub|or]2 ax,%[#|*]0%3 mov %1,al = %2 byte ptr %1,%0%3 mov %[ax|bx]2,%1 %[shl|shr|rol|ror|rcl]4 %[ax|bx]2,%3 mov %1,%[ax|bx]2 = %4 %1,%3 mov %2,%1 and al,%[#|*]0%1 xor ah,ah = and ax,%0%1 call idiv_u = xor dx,dx div bx call idiv_ = cwd idiv bx call imodu = xor dx,dx div bx mov ax,dx call imod = cwd idiv bx mov ax,dx call imul_u = imul bx call imul_ = imul bx # Rules for comparing short values 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 mov ax,%[#|*]0%1 cmp ax,%2 %[jbe |jae |jne |jge |jle ]3 %4 = cmp word ptr %2,%0%1 %=[jbe |jae |jne |jge |jle ][jae |jbe |jne |jle |jge ]3 %4 mov ax,%[#|*]0%1 cmp ax,%2 %[jb |ja |je |jg |jl ]3 %4 = cmp word ptr %2,%0%1 %=[jb |ja |je |jg |jl ][ja |jb |je |jl |jg ]3 %4 push ax mov al,%1 xor ah,ah cmp ax,%2[bp] lea sp,%(%2+2)[bp] = mov dl,%1 xor dh,dh cmp dx,ax push ax %[movzx|movsx|mov]3 ax,%1 cmp ax,%2[bp] lea sp,%(%2+2)[bp] = %3 dx,%1 cmp dx,ax # General comparison rules xor %1,%1 mov %2,%3 cmp %2,%1 = mov %2,%3 test %2,%2 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 test %1,%2 test eax,eax = test %1,%2 # 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 %[ax|bx|cx|dx]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],%1 inc %2 inc %2 push %[ax|bx|cx|dx]1 dec %[si|di]2 dec %[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],%1 dec %2 dec %2 push %[a|b|c|d]1x inc %[si|di]2 mov %[a|b|c|d]3x,%*[bp] mov %4[%[si|di]2],%[a|b|c|d]3l inc sp inc sp = mov byte ptr %(%4+1)[%2],%1l inc %2 push %[a|b|c|d]1x dec %[si|di]2 mov %[a|b|c|d]3x,%*[bp] mov %4[%[si|di]2],%[a|b|c|d]3l inc sp inc sp = mov byte ptr %(%4-1)[%2],%1l dec %2 push %1 mov %[ax|bx|cx|dx]3,%2 %[add|sub|and|xor|or]4 %[ax|bx|cx|dx]3,%*[bp] inc sp inc sp = mov %3,%2 %4 %3,%1 push %[bx|cx|dx]1 %[add|sub|and|xor|or]2 ax,%*[bp] inc sp inc sp = %2 ax,%1 push ax mov %[ax|bx|cx]3,%2 %[add|and|xor|or]4 %[ax|bx|cx]3,%*[bp] inc sp inc sp = mov dx,%2 mov %3,ax %4 %3,dx push %1 mov %[ax|bx|cx|dx]3,%2 %[add|sub|and|xor|shl|shr|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 ax mov %[ax|bx|cx]3,%2 %[add|and|xor|shl|shr|or]5 %[ax|bx|cx]3,%6 %[add|and|xor|or]4 %[ax|dx|cx]3,%*[bp] inc sp inc sp = mov dx,%2 mov %3,ax %5 dx,%6 %4 %3,dx 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 %[mov|add]1 %2,#%3 add %2,*%4 = %1 %2,#%3+%4 %[mov|add]1 %2,#%3 sub %2,*%4 = %1 %2,#%3-%4 sub %2,#%3 add %2,*%4 = %1 %2,#%3-%4 sub %2,#%3 sub %2,*%4 = %1 %2,#%3+%4 xor ax,ax mov %1,ax xor ax,ax mov %2,ax = xor ax,ax mov %1,ax mov %2,ax mov ax,%1 %[mov|add|sub|and|xor|or]2 %3,ax mov ax,%1 %[mov|add|sub|and|xor|or]4 %5,ax = mov ax,%1 %2 %3,ax %4 %5,ax call _getds = mov ax,ds mov ax,ds push ax = push ds push %[si|di]1 mov ax,ds pop %[si|di]1 = mov ax,ds # Rules to remove superflous mov instructions mov %1,%2 mov %1,%2 = mov %1,%2 mov %1,%2 mov %1,%3[bp] = mov %1,%3[bp] 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 = !mov %1,%1 # 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 br %[ | ]*.%1 jmp%[ | ]*.%2 = br .%1 ret jmp%[ | ]*%2 = ret jmp%[ | ]*.%1 .%1: = .%1: jmp%[ | ]*.%1 .%2: .%1: = .%2: .%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 push bp mov bp,sp mov %[si|di]3,%1 add sp,*%2 = push bp mov bp,sp 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 push bp mov bp,sp mov %[si|di]3,%1 dec sp dec sp = push bp mov bp,sp dec sp dec sp mov %3,%1 add sp,*%1 add sp,%[*|#]0%2 = add sp,%0%2+%1 inc sp inc sp add sp,%[*|#]0%2 = add sp,%0%2+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 proc_start call %1 proc_end = jmp near %1 push bp mov bp,sp call %1 mov sp,bp pop bp ret = jmp near %1 mov -%1[bp],%[si|di]2 call %3 add sp,%4 pop %[si|di]2 = call %3 add sp,%4 pop %2 mov -%1[bp],%[si|di]2 call %3 pop %[si|di]2 = call %3 pop %2