diff --git a/mach/i86/ce/.distr b/mach/i86/ce/.distr new file mode 100644 index 000000000..71454cacd --- /dev/null +++ b/mach/i86/ce/.distr @@ -0,0 +1,6 @@ +EM_table +as.c +as.h +as_table +mach.c +mach.h diff --git a/mach/i86/ce/EM_table b/mach/i86/ce/EM_table new file mode 100644 index 000000000..eb5017fd1 --- /dev/null +++ b/mach/i86/ce/EM_table @@ -0,0 +1,1146 @@ +#define PUSH_POP_OPT TRUE + +/******************************************************************************/ +/* */ +/* Group 1 : load instructions */ +/* */ +/******************************************************************************/ + +C_loc ==> "mov ax, $1"; + "push ax". + +C_ldc ==> C_loc( $1>>16); + C_loc( $1). + +C_lol ==> "push $1(bp)". + +C_loe.. ==> "push ($1+$2)". + +C_lil ==> "mov bx, $1(bp)"; + "push (bx)". + +C_lof ==> "pop bx"; + "push $1(bx)". + +C_lal ==> "lea ax, $1(bp)"; + "push ax". + +C_lae.. ==> "mov ax, $1+$2"; + "push ax". + +C_lxl + $1 == 0 ==> "push bp". + + $1 == 1 ==> "push 4(bp)". + + default ==> "mov cx, $1-1"; + "mov bx, 4(bp)"; + "1: mov bx, 4(bx)"; + "loop 1b"; + "push bx". + +C_lxa + $1 == 0 ==> "lea ax, 4(bp)"; + "push ax". + + $1 == 1 ==> "mov ax, 4(bp)"; + "add ax, 4"; + "push ax". + + default ==> "mov cx, $1-1"; + "mov bx, 4(bp)"; + "1: mov bx, 4(bx)"; + "loop 1b"; + "add bx, 4"; + "push bx". + +C_loi + $1 == 1 ==> "pop bx"; + "xor ax, ax"; + "movb al, (bx)"; + "push ax". + + $1 == 2 ==> "pop bx"; + "push (bx)". + + $1 == 4 ==> "pop bx"; + "push 2(bx)"; + "push (bx)". + + default ==> "pop bx"; + "mov cx, $1"; + "call .loi". + +C_los + $1 == 2 ==> "pop cx"; + "pop bx"; + "call .loi". + + default ==> arg_error( "C_los", $1). + +C_los_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop cx"; + "pop bx"; + "call .loi". + +C_ldl ==> "push $1+2(bp)"; + "push $1(bp)". + +C_lde.. ==> "push ($1+$2+2)"; + "push ($1+$2)". + +C_ldf ==> "pop bx"; + "push $1+2(bx)"; + "push $1(bx)". + +C_lpi ==> "mov ax, $1"; + "push ax". + +/******************************************************************************/ +/* */ +/* Group 2 : store instructions */ +/* */ +/******************************************************************************/ + +C_stl ==> "pop $1(bp)". + +C_ste.. ==> "pop ($1+$2)". + +C_sil ==> "mov bx, $1(bp)"; + "pop (bx)". + +C_stf ==> "pop bx"; + "pop $1(bx)". + +C_sti + $1 == 1 ==> "pop bx"; + "pop ax"; + "movb (bx), al". + + $1 == 2 ==> "pop bx"; + "pop (bx)". + + $1 == 4 ==> "pop bx"; + "pop (bx)"; + "pop 2(bx)". + + default ==> "pop bx"; + "mov cx, $1"; + "call .sti". + +C_sts + $1 == 2 ==> "pop cx"; + "pop bx"; + "call .sti". + + default ==> arg_error( "C_sts", $1). + +C_sts_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop cx"; + "pop bx"; + "call .sti". + +C_sdl ==> "pop $1(bp)"; + "pop $1+2(bp)". + +C_sde.. ==> "pop ($1+$2)"; + "pop ($1+$2+2)". + +C_sdf ==> "pop bx"; + "pop $1(bx)"; + "pop $1+2(bx)". + +/******************************************************************************/ +/* */ +/* Group 3 : integer arithmetic */ +/* */ +/******************************************************************************/ + +C_adi + $1 == 2 ==> "pop ax"; + "pop bx"; + "add ax, bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "add ax, cx"; + "adc bx, dx"; + "push bx"; + "push ax". + + default ==> "pop ax"; + "mov cx, $1"; + "call .adi"; + "push ax". + +C_adi_narg ==> "pop cx"; + "pop ax"; + "call .adi"; + "push ax". + +C_sbi + $1 == 2 ==> "pop bx"; + "pop ax"; + "sub ax, bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "sub cx, ax"; + "sbb dx, bx"; + "push dx"; + "push cx". + + default ==> "pop ax"; + "mov cx, $1"; + "call .sbi"; + "push ax". + +C_sbi_narg ==> "pop cx"; + "pop ax"; + "call .sbi"; + "push ax". + +C_mli + $1 == 2 ==> "pop ax"; + "pop bx"; + "mul bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop dx"; + "call .mli4"; + "push dx"; + "push ax". + + default ==> arg_error( "C_mli", $1). + +C_mli_narg ==> "pop ax"; + "call .mli". + +C_dvi + $1 == 2 ==> "pop bx"; + "pop ax"; + "cwd"; + "idiv bx"; + "push ax". + + $1 == 4 ==> "call .dvi4"; + "push dx"; + "push ax". + + default ==> arg_error( "C_dvi", $1). + +C_dvi_narg ==> "pop ax"; + "call .dvi". + +C_rmi + $1 == 2 ==> "pop bx"; + "pop ax"; + "cwd"; + "idiv bx"; + "push dx". + + $1 == 4 ==> "call .rmi4"; + "push dx"; + "push ax". + + default ==> arg_error( "C_rmi", $1). + +C_rmi_narg ==> "pop ax"; + "call .rmi". + +C_ngi + $1 == 2 ==> "pop ax"; + "neg ax"; + "push ax". + + $1 == 4 ==> "pop bx"; + "pop ax"; + "neg ax"; + "neg bx"; + "sbb ax, 0"; + "push ax"; + "push bx". + + default ==> "mov ax, $1"; + "call .ngi". + +C_ngi_narg ==> "pop ax"; + "call .ngi". + +C_sli + $1 == 2 ==> "pop cx"; + "pop ax"; + "sal ax, cl"; + "push ax". + + default ==> "mov ax, $1"; + "call .sli". + +C_sli_narg ==> "pop ax"; + "call .sli". + +C_sri + $1 == 2 ==> "pop cx"; + "pop ax"; + "sar ax, cl"; + "push ax". + + default ==> "mov ax, $1"; + "call .sri". + +C_sri_narg ==> "pop ax"; + "call .sri". + +/******************************************************************************/ +/* */ +/* Group 4 : Unsigned arithmetic */ +/* */ +/******************************************************************************/ + +C_adu ==> C_adi( $1). + +C_adu_narg ==> C_adi_narg(). + +C_sbu ==> C_sbi( $1). + +C_sbu_narg ==> C_sbi_narg(). + +C_mlu ==> C_mli( $1). + +C_mlu_narg ==> C_mli_narg(). + +C_dvu + $1 == 2 ==> "pop bx"; + "pop ax"; + "xor dx, dx"; + "div bx"; + "push ax". + + $1 == 4 ==> "call .dvu4"; + "push dx"; + "push ax". + + default ==> "mov ax, $1"; + "call .dvu". + +C_dvu_narg ==> "pop ax"; + "call .dvu". + +C_rmu + $1 == 2 ==> "pop bx"; + "pop ax"; + "xor dx, dx"; + "div bx"; + "push dx". + + $1 == 4 ==> "call .dvu4"; + "push dx"; + "push ax". + + default ==> "mov ax, $1"; + "call .rmu". + +C_rmu_narg ==> "pop ax"; + "call .rmu". + +C_slu ==> C_sli( $1). + +C_slu_narg ==> C_sli_narg(). + +C_sru + $1 == 2 ==> "pop cx"; + "pop ax"; + "shr ax, cl"; + "push ax". + + $1 == 4 ==> "pop cx"; + "pop bx"; + "pop ax"; + "1 : shr ax, 1"; + "rcr bx, 1"; + "loop 1b"; + "push ax"; + "push bx". + + default ==> arg_error( "C_sru", $1). + +/******************************************************************************/ +/* */ +/* Group 5 : Floating point arithmetic */ +/* */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Group 6 : Pointer arithmetic */ +/* */ +/******************************************************************************/ + +C_adp + +#ifndef PEEPHOLE_OPT + $1 == 0 ==> . +#endif + + $1 == 1 ==> "pop ax"; + "inc ax"; + "push ax". + + $1 == -1 ==> "pop ax"; + "dec ax"; + "push ax". + + default ==> "pop ax"; + "add ax, $1"; + "push ax". + +C_ads + $1 == 2 ==> "pop ax"; + "pop bx"; + "add ax, bx"; + "push ax". + + default ==> arg_error( "C_ads", $1). + +C_ads_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop ax"; + "pop bx"; + "add ax, bx"; + "push ax". + +C_sbs + $1 == 2 ==> "pop bx"; + "pop ax"; + "sub ax, bx"; + "push ax". + + default ==> arg_error( "C_sbs", $1). + +C_sbs_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop bx"; + "pop ax"; + "sub ax, bx"; + "push ax". + +/******************************************************************************/ +/* */ +/* Group 7 : Increment/decrement/zero */ +/* */ +/******************************************************************************/ + +C_inc ==> "pop ax"; + "inc ax"; + "push ax". + +C_inl ==> "inc $1(bp)". + +C_ine.. ==> "inc ($1+$2)". + +C_dec ==> "pop ax"; + "dec ax"; + "push ax". + +C_del ==> "dec $1(bp)". + +C_dee.. ==> "dec ($1+$2)". + +C_zrl ==> "mov $1(bp), 0". + +C_zre.. ==> "mov ($1+$2), 0". + +C_zer + $1 == 2 ==> "xor ax, ax"; + "push ax". + + $1 == 4 ==> "xor ax, ax"; + "push ax"; + "push ax". + + $1 == 6 ==> "xor ax, ax"; + "push ax"; + "push ax"; + "push ax". + + $1 == 8 ==> "xor ax, ax"; + "push ax"; + "push ax"; + "push ax"; + "push ax". + + $1 % 2 == 0 ==> "mov cx, $1/2"; + "xor ax, ax"; + "1: push ax"; + "loop 1b". + + default ==> arg_error( "C_zer", $1). + +C_zer_narg ==> "pop cx"; + "sar cx, 1"; + "xor ax, ax"; + "1: push ax"; + "loop 1b". + +/******************************************************************************/ +/* */ +/* Group 8 : Convert */ +/* */ +/******************************************************************************/ + +C_cii ==> "pop cx"; + "pop dx"; + "pop ax"; + "call .cii"; + "push ax". + +C_cui ==> C_cuu(). + +C_ciu ==> C_cuu(). + +C_cuu ==> "pop cx"; + "pop dx"; + "pop ax"; + "call .cuu"; + "push ax". + +/******************************************************************************/ +/* */ +/* Group 9 : Logical */ +/* */ +/******************************************************************************/ + +C_and + $1 == 2 ==> "pop ax"; + "pop bx"; + "and ax, bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "and ax, cx"; + "and bx, dx"; + "push bx"; + "push ax". + + default ==> "mov cx, $1"; + "call .and". + +C_and_narg ==> "pop cx"; + "call .and". + +C_ior + $1 == 2 ==> "pop ax"; + "pop bx"; + "or ax, bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "or ax, cx"; + "or bx, dx"; + "push bx"; + "push ax". + + default ==> "mov cx, $1"; + "call .ior". + +C_ior_narg ==> "pop cx"; + "call .ior". + +C_xor + $1 == 2 ==> "pop ax"; + "pop bx"; + "xor ax, bx"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "xor ax, cx"; + "xor bx, dx"; + "push bx"; + "push ax". + + default ==> "mov cx, $1"; + "call .xor". + +C_xor_narg ==> "pop cx"; + "call .xor". + +C_com + $1 == 2 ==> "pop ax"; + "not ax"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "not ax"; + "not bx"; + "push bx"; + "push ax". + + default ==> "mov cx, $1"; + "call .com". + +C_com_narg ==> "pop cx"; + "call .com". + +C_rol + $1 == 2 ==> "pop cx"; + "pop ax"; + "rol ax, cl"; + "push ax". + + default ==> "mov cx, $1"; + "call .rol". + +C_rol_narg ==> "pop cx"; + "call .rol". + +C_ror + $1 == 2 ==> "pop cx"; + "pop ax"; + "ror ax, cl"; + "push ax". + + default ==> "mov cx, $1"; + "call .ror". + +C_ror_narg ==> "pop cx"; + "call .ror". + +/******************************************************************************/ +/* */ +/* Group 10 : Sets */ +/* */ +/******************************************************************************/ + +C_inn + $1 == 2 ==> "pop cx"; + "pop ax"; + "shr ax, cl"; + "and ax, 1"; + "push ax". + + default ==> "pop ax"; + "mov cx, $1"; + "call .inn"; + "push ax". + +C_inn_narg ==> "pop cx"; + "pop ax"; + "call .inn"; + "push ax". + +C_set + $1 == 2 ==> "pop cx"; + "mov ax, 1"; + "shl ax, cl"; + "push ax". + + default ==> "pop ax"; + "mov cx, $1"; + "call .set". + +C_set_narg ==> "pop cx"; + "pop ax"; + "call .set". + +/******************************************************************************/ +/* */ +/* Group 11 : Array */ +/* */ +/******************************************************************************/ + +C_lar + $1 == 2 ==> "pop bx"; + "pop ax"; + "call .lar2". + + default ==> arg_error( "C_lar", $1). + +C_lar_narg ==> "call .ilar". + +C_sar + $1 == 2 ==> "pop bx"; + "pop ax"; + "call .sar2". + + default ==> arg_error( "C_sar", $1). + +C_sar_narg ==> "call .isar". + +C_aar + $1 == 2 ==> "pop bx"; + "pop ax"; + "pop cx"; + "sub ax, (bx)"; + "mul 4(bx)"; + "add ax, cx"; + "push ax". + + default ==> arg_error( "C_aar", $1). + +C_aar_narg ==> "call .iaar"; + "push bx". + +/******************************************************************************/ +/* */ +/* Group 12 : Compare */ +/* */ +/******************************************************************************/ + +C_cmi + $1 == 2 ==> /* bug : C_sbi( (arith) 2). */ + "pop bx"; + "pop cx"; + "xor ax, ax"; + "cmp cx, bx"; + "je 2f"; + "jl 1f"; + "inc ax"; + "jmp 2f"; + "1: dec ax"; + "2: push ax". + + $1 == 4 ==> "call .cmi4"; + "push ax". + + default ==> arg_error( "C_cmi", $1). + +C_cmu + $1 == 2 ==> C_cmp(). + + $1 == 4 ==> "call .cmu4"; + "push ax". + + default ==> arg_error( "C_cmu", $1). + +C_cms + $1 == 2 ==> C_sbi( (arith) 2). + + $1 == 4 ==> "pop ax"; + "pop bx"; + "pop cx"; + "pop dx"; + "sub cx, ax"; + "sbb dx, bx"; + "jne 1f"; + "or dx, cx"; + "1: push dx". + + default ==> "mov cx, $1"; + "call .cms"; + "push cx". + +C_cms_narg ==> "pop cx"; + "call .cms"; + "push cx". + +C_cmp ==> "pop bx"; + "pop cx"; + "xor ax, ax"; + "cmp cx, bx"; + "je 2f"; + "jb 1f"; + "inc ax"; + "jmp 2f"; + "1: dec ax"; + "2: push ax". + +C_tlt ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "jge 1f"; + "inc bx"; + "1: push bx". + +C_tle ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "jg 1f"; + "inc bx"; + "1: push bx". + +C_teq ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "jne 1f"; + "inc bx"; + "1: push bx". + +C_tne ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "je 1f"; + "inc bx"; + "1: push bx". + +C_tge ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "jl 1f"; + "inc bx"; + "1: push bx". + +C_tgt ==> "pop ax"; + "xor bx, bx"; + "test ax, ax"; + "jle 1f"; + "inc bx"; + "1: push bx". + +/******************************************************************************/ +/* */ +/* Group 13 : Branch */ +/* */ +/******************************************************************************/ + +C_bra ==> "jmp $1". + +C_blt ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "jl $1". + +C_ble ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "jle $1". + +C_beq ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "je $1". + +C_bne ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "jne $1". + +C_bge ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "jge $1". + +C_bgt ==> "pop ax"; + "pop bx"; + "cmp bx, ax"; + "jg $1". + +C_zlt ==> "pop ax"; + "test ax, ax"; + "jl $1". + +C_zle ==> "pop ax"; + "test ax, ax"; + "jle $1". + +C_zeq ==> "pop ax"; + "test ax, ax"; + "je $1". + +C_zne ==> "pop ax"; + "test ax, ax"; + "jne $1". + +C_zge ==> "pop ax"; + "test ax, ax"; + "jge $1". + +C_zgt ==> "pop ax"; + "test ax, ax"; + "jg $1". + +/******************************************************************************/ +/* */ +/* Group 14 : Procedure call instructions */ +/* */ +/******************************************************************************/ + +C_cai ==> "pop bx"; + "call bx". + +C_cal ==> "call $1". + +C_lfr + $1 == 2 ==> "push ax". + + $1 == 4 ==> "push dx"; + "push ax". + + $1 == 6 ==> "call .lfr6". + + $1 == 8 ==> "call .lfr8". + + default ==> arg_error( "C_lfr", $1). + +C_ret + $1 == 0 ==> "mov sp, bp"; + "pop bp"; + "ret". + + $1 == 2 ==> "pop ax"; + "mov sp, bp"; + "pop bp"; + "ret". + + $1 == 4 ==> "pop ax"; + "pop dx"; + "mov sp, bp"; + "pop bp"; + "ret". + + $1 == 6 ==> "call .ret6"; + "mov sp, bp"; + "pop bp"; + "ret". + + $1 == 8 ==> "call .ret8"; + "mov sp, bp"; + "pop bp"; + "ret". + + default ==> arg_error( "C_ret", $1). + +/******************************************************************************/ +/* */ +/* Group 15 : Miscellaneous instructions */ +/* */ +/******************************************************************************/ + +C_asp + $1 == 2 ==> "pop bx". + + $1 == 4 ==> "pop bx"; + "pop bx". + + $1 == -2 ==> "push ax". + + default ==> "add sp, $1". + +C_ass + $1 == 2 ==> "pop ax"; + "add sp, ax". + + default ==> arg_error( "C_ass", $1). + +C_ass_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop ax"; + "add sp, ax". + +C_blm + $1 % 2 == 0 ==> "mov cx, $1/2"; + "call .blm". + + default ==> arg_error( "C_blm", $1). + +C_bls + $1 == 2 ==> "pop cx"; + "sar cx,1"; + "call .blm". + + default ==> arg_error( "C_bls", $1). + +C_bls_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop cx"; + "sar cx, 1"; + "call .blm". + +C_csa + $1 == 2 ==> "pop bx"; + "pop ax"; + "jmp .csa2". + + default ==> arg_error( "C_csa", $1). + +C_csa_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop bx"; + "pop ax"; + "jmp .csa2". + +C_csb + $1 == 2 ==> "pop bx"; + "pop ax"; + "jmp .csb2". + + default ==> arg_error( "C_csb", $1). + +C_csb_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop bx"; + "pop ax"; + "jmp .csb2". + +C_dch ==> "mov bp, (bp)". + +C_dup + $1 == 2 ==> "pop ax"; + "push ax"; + "push ax". + + $1 == 4 ==> "pop ax"; + "pop bx"; + "push bx"; + "push ax"; + "push bx"; + "push ax". + + default ==> "mov cx, $1"; + "call .dup". + +C_dus + $1 == 2 ==> "pop cx"; + "call .dup". + + default ==> arg_error( "C_dus", $1). + +C_dus_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop cx"; + "call .dup". + +C_exg ==> "mov cx, $1"; + "call .exg". + +C_exg_narg ==> "pop cx"; + "call .exg". + +C_fil.. ==> "mov (hol0+4), $1+$2". + +C_gto.. ==> "mov bx, $1+$2"; + "call .gto". + +C_lim ==> "push (.ignmask)". + +C_lin ==> "mov (hol0), $1". + +C_lni ==> "inc (hol0)". + +C_lor + $1 == 0 ==> "push bp". + + $1 == 1 ==> "mov ax, sp"; + "push ax". + + $1 == 2 ==> "push (.reghp)". + + default ==> arg_error( "C_lor", $1). + +C_lpb ==> "add bp, 4". + +C_mon ==> "pop ax"; + "call .mon". + +C_nop ==> "call .nop". + +C_rck + $1 == 2 ==> "pop bx"; + "pop ax"; + "call .rck"; + "push ax". + + default ==> arg_error( "C_rck", $1). + +C_rck_narg ==> "pop ax"; + "cmp ax, 2"; + "jne .unknown"; + "pop bx"; + "pop ax"; + "call .rck"; + "push ax". + + +C_rtt ==> C_ret( (arith) 0). + +C_sig ==> "pop ax"; + "xchg (.trppc), ax"; + "push ax". + +C_sim ==> "pop (.ignmask)". + +C_str + $1 == 0 ==> "pop bp". + + $1 == 1 ==> "pop sp". + + $1 == 2 ==> "pop (.reghp)". + + default ==> arg_error( "C_str", $1). + +C_trp ==> "pop ax"; + "call .trp". + +/******************************************************************************/ +/* */ +/* Storage-routines */ +/* */ +/******************************************************************************/ + + +..icon + $2 == 1 ==> gen1( (ONE_BYTE) atoi( $1)). + $2 == 2 ==> gen2( (TWO_BYTES) atoi( $1)). + $2 == 4 ==> gen4( (FOUR_BYTES) atol( $1)). + default ==> arg_error( "..icon", $1). + +..ucon + $2 == 1 ==> gen1( (ONE_BYTE) atoi( $1)). + $2 == 2 ==> gen2( (TWO_BYTES) atoi( $1)). + $2 == 4 ==> gen4( (FOUR_BYTES) atol( $1)). + default ==> arg_error( "..ucon", $1). + +/******************************************************************************/ +/* */ +/* Extra-routines */ +/* */ +/******************************************************************************/ + +#ifdef PUSH_POP_OPT + +C_df_ilb ==> clean_push_buf(); + symbol_definition( $1); + set_local_visible( $1). +#endif + +jump ==> "jmp $1". + +prolog ==> "push bp"; + "mov bp, sp". + +locals + $1 == 0 ==> . + + $1 == 2 ==> "push ax". + + $1 == 4 ==> "push ax"; + "push ax". + + default ==> "sub sp, $1". diff --git a/mach/i86/ce/as.c b/mach/i86/ce/as.c new file mode 100644 index 000000000..9d7d1dc85 --- /dev/null +++ b/mach/i86/ce/as.c @@ -0,0 +1,312 @@ +#include "arg_type.h" +#include "as.h" + +static struct t_operand dummy = { IS_REG, AX, 0, 0, 0}; +struct t_operand saved_op, *AX_oper = &dummy; + +save_op( op) +struct t_operand *op; +{ + saved_op.type = op->type; + saved_op.reg = op->reg; + saved_op.expr = op->expr; + saved_op.lab = op->lab; + saved_op.off = op->off; +} + +#define last( s) ( s + strlen( s) - 1) +#define LEFT '(' +#define RIGHT ')' +#define DOLLAR '$' + +block_assemble( instr, nr, first, Last) +char **instr; +int nr, first, Last; +{ + int i; + + if ( first) { + if( strncmp( instr[0], "pop", 3) == 0) { + *instr[0] = 'P'; + *( instr[0]+1) = 'O'; + *( instr[0]+2) = 'P'; + } + else + @clean_push_buf(); + } + if ( Last && strncmp( instr[nr-1], "push", 4) == 0) { + *instr[nr-1] = 'P'; + *( instr[nr-1]+1) = 'U'; + *( instr[nr-1]+2) = 'S'; + *( instr[nr-1]+3) = 'H'; + } + + for( i=0; i IS_DATA en IS_LABEL + * reg -> IS_REG en IS_ACCU + * (expr) -> IS_ADDR + * expr(reg) -> IS_MEM + */ +{ + char *ptr, *index(); + + op->type = UNKNOWN; + if ( *last( str) == RIGHT) { + ptr = index( str, LEFT); + *last( str) = '\0'; + *ptr = '\0'; + if ( is_reg( ptr+1, op)) { + op->type = IS_MEM; + op->expr = ( *str == '\0' ? "0" : str); + } + else { + set_label( ptr+1, op); + op->type = IS_ADDR; + } + } + else + if ( is_reg( str, op)) + op->type = IS_REG; + else { + if ( contains_label( str)) + set_label( str, op); + else { + op->type = IS_DATA; + op->expr = str; + } + } +} + +int is_reg( str, op) +char *str; +struct t_operand *op; +{ + if ( strlen( str) != 2) + return( 0); + + switch ( *(str+1)) { + case 'x' : + case 'l' : switch( *str) { + case 'a' : op->reg = 0; + return( TRUE); + + case 'c' : op->reg = 1; + return( TRUE); + + case 'd' : op->reg = 2; + return( TRUE); + + case 'b' : op->reg = 3; + return( TRUE); + + default : return( FALSE); + } + + case 'h' : switch( *str) { + case 'a' : op->reg = 4; + return( TRUE); + + case 'c' : op->reg = 5; + return( TRUE); + + case 'd' : op->reg = 6; + return( TRUE); + + case 'b' : op->reg = 7; + return( TRUE); + + default : return( FALSE); + } + + case 'p' : switch ( *str) { + case 's' : op->reg = 4; + return( TRUE); + + case 'b' : op->reg = 5; + return( TRUE); + + default : return( FALSE); + } + + case 'i' : switch ( *str) { + case 's' : op->reg = 6; + return( TRUE); + + case 'd' : op->reg = 7; + return( TRUE); + + default : return( FALSE); + } + + default : return( FALSE); + } +} + +#include +#define isletter( c) ( isalpha( c) || c == '_') + +int contains_label( str) +char *str; +{ + while( !isletter( *str) && *str != '\0') + if ( *str == '$') + if ( arg_type( str) == STRING) + return( TRUE); + else + str += 2; + else + str++; + + return( isletter( *str)); +} + +set_label( str, op) +char *str; +struct t_operand *op; +{ + char *ptr, *index(), *sprint(); + static char buf[256]; + + ptr = index( str, '+'); + + if ( ptr == 0) + op->off = "0"; + else { + *ptr = '\0'; + op->off = ptr + 1; + } + + if ( isdigit( *str) && ( *(str+1) == 'b' || *(str+1) == 'f') && + *(str+2) == '\0') { + *(str+1) = '\0'; /* b of f verwijderen! */ + op->lab = str; + op->type = IS_ILB; + } + else { + op->type = IS_LABEL; + if ( index( str, DOLLAR) != 0) + op->lab = str; + else + /* nood oplossing */ + op->lab = sprint( buf, "\"%s\"", str); + } +} + + +/******************************************************************************/ + + + +mod_RM( reg, op) +int reg; +struct t_operand *op; +{ + if ( REG( op)) + R233( 0x3, reg, op->reg); + else if ( ADDR( op)) { + R233( 0x0, reg, 0x6); + @reloc2( %$(op->lab), %$(op->off), ABSOLUTE); + } + else if ( strcmp( op->expr, "0") == 0) + switch( op->reg) { + case SI : R233( 0x0, reg, 0x4); + break; + + case DI : R233( 0x0, reg, 0x5); + break; + + case BP : R233( 0x1, reg, 0x6); /* Uitzondering! */ + @text1( 0); + break; + + case BX : R233( 0x0, reg, 0x7); + break; + + default : fprint( STDERR, "Wrong index register %d\n", + op->reg); + } + else { + @if ( fit_byte( %$(op->expr))) + switch( op->reg) { + case SI : R233( 0x1, reg, 0x4); + break; + + case DI : R233( 0x1, reg, 0x5); + break; + + case BP : R233( 0x1, reg, 0x6); + break; + + case BX : R233( 0x1, reg, 0x7); + break; + + default : fprint( STDERR, "Wrong index register %d\n", + op->reg); + } + @text1( %$(op->expr)); + @else + switch( op->reg) { + case SI : R233( 0x2, reg, 0x4); + break; + + case DI : R233( 0x2, reg, 0x5); + break; + + case BP : R233( 0x2, reg, 0x6); + break; + + case BX : R233( 0x2, reg, 0x7); + break; + + default : fprint( STDERR, "Wrong index register %d\n", + op->reg); + } + @text2( %$(op->expr)); + @fi + } +} + +mov_REG_EADDR( dst, src) +struct t_operand *dst, *src; +{ + if ( REG(src) && dst->reg == src->reg) + ; /* Nothing!! result of push/pop optimization */ + else { + @text1( 0x8b); + mod_RM( dst->reg, src); + } +} + + +R233( a, b, c) +int a,b,c; +{ + @text1( %d( (a << 6) | ( b << 3) | c)); +} + + +R53( a, b) +int a,b; +{ + @text1( %d( (a << 3) | b)); +} diff --git a/mach/i86/ce/as.h b/mach/i86/ce/as.h new file mode 100644 index 000000000..e39e6871c --- /dev/null +++ b/mach/i86/ce/as.h @@ -0,0 +1,40 @@ +#define UNKNOWN 0 +#define IS_REG 0x1 +#define IS_ACCU 0x2 +#define IS_DATA 0x4 +#define IS_LABEL 0x8 +#define IS_MEM 0x10 +#define IS_ADDR 0x20 +#define IS_ILB 0x40 + +#define AX 0 +#define BX 3 +#define CL 1 +#define SP 4 +#define BP 5 +#define SI 6 +#define DI 7 + +#define REG( op) ( op->type & IS_REG) +#define ACCU( op) ( op->type & IS_REG && op->reg == AX) +#define REG_CL( op) ( op->type & IS_REG && op->reg == CL) +#define DATA( op) ( op->type & IS_DATA) +#define lABEL( op) ( op->type & IS_LABEL) +#define ILB( op) ( op->type & IS_ILB) +#define MEM( op) ( op->type & IS_MEM) +#define ADDR( op) ( op->type & IS_ADDR) +#define EADDR( op) ( op->type & ( IS_ADDR | IS_MEM | IS_REG)) +#define CONST1( op) ( op->type & IS_DATA && strcmp( "1", op->expr) == 0) +#define MOVS( op) ( op->type & IS_LABEL&&strcmp("\"movs\"", op->lab) == 0) +#define IMMEDIATE( op) ( op->type & ( IS_DATA | IS_LABEL)) + +#define TRUE 1 +#define FALSE 0 + +struct t_operand { + unsigned type; + int reg; + char *expr, *lab, *off; + }; + +extern struct t_operand saved_op, *AX_oper; diff --git a/mach/i86/ce/as_table b/mach/i86/ce/as_table new file mode 100644 index 000000000..dbc400c21 --- /dev/null +++ b/mach/i86/ce/as_table @@ -0,0 +1,228 @@ +adc dst:REG, src:EADDR ==> @text1( 0x13); + mod_RM( dst->reg, src). + +add dst:REG, src:EADDR ==> @text1( 0x3); + mod_RM( dst->reg, src). + +... dst:ACCU, src:DATA ==> @text1( 0x5); + @text2( %$(src->expr)). + +... dst:EADDR, src:DATA ==> @text1( 0x81); + mod_RM( 0, dst); + @text2( %$(src->expr)). + +... dst:ACCU, src:lABEL ==> @text1( 0x5); + @reloc2( %$(src->lab), %$(src->off), !PC_REL). + +... dst:EADDR, src:lABEL ==> @text1( 0x81); + mod_RM( 0, dst); + @reloc2( %$(src->lab), %$(src->off), !PC_REL). + +and dst:REG, src:EADDR ==> @text1( 0x23); + mod_RM( dst->reg, src). + +... dst:ACCU, src:DATA ==> @text1( 0x25); + @text2( %$(src->expr)). + +call dst:lABEL ==> @text1( 0xe8); + @reloc2( %$(dst->lab), %$(dst->off), PC_REL). + +... dst:EADDR ==> @text1( 0xff); + mod_RM( 2, dst). + +cmp dst:REG, src:EADDR ==> @text1( 0x3b); + mod_RM( dst->reg, src). + +... dst:ACCU, src:DATA ==> @text1( 0x3d); + @text2( %$(src->expr)). + +cwd ==> @text1( 0x99). + +dec dst:REG ==> R53( 9, dst->reg). + +... dst:EADDR ==> @text1( 0xff); + mod_RM( 1, dst). + +div divisor:EADDR ==> @text1( 0xf7); + mod_RM( 6, divisor). + +idiv divisor:EADDR ==> @text1( 0xf7); + mod_RM( 7, divisor). + +inc dst:REG ==> R53( 8, dst->reg). + +... dst:EADDR ==> @text1( 0xff); + mod_RM( 0, dst). + +jb dst:ILB ==> @text1( 0x72); + @text1( %dist( dst->lab)). + +je dst:ILB ==> @text1( 0x74); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "jne 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +jg dst:ILB ==> @text1( 0x7f); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "jle 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +jge dst:ILB ==> @text1( 0x7d); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "jl 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +jl dst:ILB ==> @text1( 0x7c); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "jge 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +jle dst:ILB ==> @text1( 0x7e); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "jg 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +jmp dst:ILB ==> @text1( 0xeb); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> @text1( 0xe9); + @reloc2( %$(dst->lab), %$(dst->off), PC_REL). + +jne dst:ILB ==> @text1( 0x75); + @text1( %dist( dst->lab)). + +... dst:lABEL ==> save_op( dst); + assemble( "je 9f"); + jmp_instr( &saved_op); + assemble( "9:"). + +lea dst:REG, src:EADDR ==> @text1( 0x8d); + mod_RM( dst->reg, src). + +loop dst:ILB ==> @text1( 0xe2); + @text1( %dist( dst->lab)). + +mov dst:REG, src:EADDR ==> mov_REG_EADDR( dst, src). + +... dst:REG, src:DATA ==> R53( 0x17, dst->reg); + @text2( %$(src->expr)). + +... dst:REG, src:lABEL ==> R53( 0x17, dst->reg); + @reloc2( %$(src->lab), %$(src->off), !PC_REL). + +... dst:EADDR, src:REG ==> @text1( 0x89); + mod_RM( src->reg, dst). + +... dst:EADDR, src:DATA ==> @text1( 0xc7); + mod_RM( 0, dst); + @text2( %$(src->expr)). + +... dst:EADDR, src:lABEL ==> @text1( 0xc7); + mod_RM( 0, dst); + @reloc2( %$(src->lab), %$(src->off), !PC_REL). + +movb dst:REG, src:EADDR ==> @text1( 0x8a); + mod_RM( dst->reg, src). + +... dst:EADDR, src:REG ==> @text1( 0x88); + mod_RM( src->reg, dst). + +mul mplier:EADDR ==> @text1( 0xf7); + mod_RM( 4, mplier). + +neg dst:EADDR ==> @text1( 0xf7); + mod_RM( 3, dst). + +not dst:EADDR ==> @text1( 0xf7); + mod_RM( 2, dst). + +or dst:REG, src:EADDR ==> @text1( 0x0b); + mod_RM( dst->reg, src). + +pop dst:REG ==> R53( 0xb, dst->reg). + +... dst:EADDR ==> @text1( 0x8f); + mod_RM( 0, dst). + +POP dst ==> @if ( push_waiting) + mov_instr( dst, AX_oper); + @assign( push_waiting, FALSE). + @else + pop_instr( dst). + @fi. + +push src:REG ==> R53( 0xa, src->reg). + +... src:EADDR ==> @text1( 0xff); + mod_RM( 6, src). + +PUSH src ==> mov_instr( AX_oper, src); + @assign( push_waiting, TRUE). + +rcr dst:EADDR, src:CONST1 ==> @text1( 0xd1); + mod_RM( 3, dst). + +rep ins:MOVS ==> @text1( 0xf3); + @text1( 0xa5). /* Wie zet direction flag? */ + +ret ==> @text1( 0xc3). /* Altijd NEAR! */ + +rol dst:EADDR, src:REG_CL ==> @text1( 0xd3); + mod_RM( 0, dst). + +ror dst:EADDR, src:REG_CL ==> @text1( 0xd3); + mod_RM( 1, dst). + +sal dst:EADDR, src:REG_CL ==> @text1( 0xd3); + mod_RM( 4, dst). + +sar dst:EADDR, src:REG_CL ==> @text1( 0xd3); + mod_RM( 7, dst). + +... dst:EADDR, src:CONST1 ==> @text1( 0xd1); + mod_RM( 7, dst). + +sbb dst:REG, src:EADDR ==> @text1( 0x1b); + mod_RM( dst->reg, src). + +... dst:ACCU, src:DATA ==> @text1( 0x1d); + @text2( %$(src->expr)). + +shl dst, src ==> sal_instr( dst, src). + +shr dst:EADDR, src:REG_CL ==> @text1( 0xd3); + mod_RM( 5, dst). + +... dst:EADDR, src:CONST1 ==> @text1( 0xd1); + mod_RM( 5, dst). + +sub dst:REG, src:EADDR ==> @text1( 0x2b); + mod_RM( dst->reg, src). + +... dst:EADDR, src:DATA ==> @text1( 0x81); + mod_RM( 5, dst); + @text2( %$(src->expr)). + +test dst:REG, src:EADDR ==> @text1( 0x85); + mod_RM( dst->reg, src). + +xchg dst:EADDR, src:REG ==> @text1( 0x87); + mod_RM( src->reg, dst). + +xor dst:REG, src:EADDR ==> @text1( 0x33); + mod_RM( dst->reg, src). diff --git a/mach/i86/ce/mach.c b/mach/i86/ce/mach.c new file mode 100644 index 000000000..437af6484 --- /dev/null +++ b/mach/i86/ce/mach.c @@ -0,0 +1,17 @@ +#include +#include "mach.h" + +arg_error( s, arg) +char *s; +int arg; +{ + fprint( STDERR, "arg_error %s %d\n", s, arg); +} + +int push_waiting = FALSE; + +int fit_byte( val) +int val; +{ + return( val >= -128 && val <= 127); +} diff --git a/mach/i86/ce/mach.h b/mach/i86/ce/mach.h new file mode 100644 index 000000000..944b262c7 --- /dev/null +++ b/mach/i86/ce/mach.h @@ -0,0 +1,26 @@ +#define BSS_INIT 0 + +#define ONE_BYTE int +#define TWO_BYTES int +#define FOUR_BYTES long + + +#define EM_WSIZE 2 +#define EM_PSIZE 2 +#define EM_BSIZE 4 + + +#define NAME_FMT "_%s" +#define DNAM_FMT "_%s" +#define DLB_FMT "I_%ld" +#define ILB_FMT "I%03d%ld" +#define HOL_FMT "hol%d" + +#define GENLAB 'I' + +#define TRUE 1 +#define FALSE 0 + +#define clean_push_buf() if(push_waiting){text1(0x50);push_waiting=FALSE;} +#define assign( l, r) l = r +extern int push_waiting;