Programming tools for your new processor
Complier Code Tables
#
# Copyright © 1994,1996 by Archelon Inc. All rights reserved.
#
# 960201 - use new style expansion of address modes
# 960125 - fixed errors on code structload
# 960125 - put stack options under new stack directive
# 941201 - added "matches($right,const16) as last predicate of asgn,
# in order to generate better code.
# 940906 - added support for output built-ins, in order to test
# with simulator.
#
mau := 8;
data_pointer := long;
code_pointer := long;
int := short;
loops_nest;
regset := R[32] width=32
optype=int,ptr,ptr2,float,double,longdbl,codeptr
regtype=char,short,int,ptr,ptr2,codeptr,long,float,double,longdbl;
scratch := R[24-27];
argreg := R[24-27];
color := R[0-29];
stack
hw_farg_offset := 4,
frameptr := R[30],
stkptr := R[31];
#
# O P E R A N D S
#
operand data_addr ptr;
operand code_addr codeptr;
operand const16 sconst -32768 32767;
operand constz uconst 0;
operand gp_reg reg R;
operand zi_addr amode data_addr expansion "%2";
operand ri_addr amode R+const16 expansion "%1,%2";
operand rr_addr amode R+R expansion "%1,%3";
#
# F O R M A T S
#
format mem_load_zi src zi_addr dest gp_reg;
format mem_load_ri src ri_addr dest gp_reg;
format mem_load_rr src rr_addr dest gp_reg;
format mem_store_rzi src gp_reg dest zi_addr;
format mem_store_rri src gp_reg dest ri_addr;
format mem_store_rrr src gp_reg dest rr_addr;
format mem_store_izi src const16 dest zi_addr;
format mem_store_iri src const16 dest ri_addr;
format mem_store_irr src const16 dest rr_addr;
format unary_rr src gp_reg dest gp_reg;
format unary_ir src const16 dest gp_reg;
format binary_rrr lsrc gp_reg rsrc gp_reg dest gp_reg;
format binary_rir lsrc gp_reg rsrc const16 dest gp_reg;
format compare_rr lsrc gp_reg rsrc gp_reg;
format compare_ri lsrc gp_reg rsrc const16;
format branch dest code_addr;
format brind lsrc gp_reg;
format noargs ;
format loop src code_addr dest code_addr ;
format loopldi src const16 dest code_addr;
format loopldr src gp_reg dest code_addr;
format output lsrc const16 rsrc gp_reg;
format outputi lsrc const16 rsrc const16;
#
# O P C O D E S
#
# access_opcode( prefix,addr_mode,access_mode )
opcode ldzi_b mem_load_zi;
opcode ldzi_w mem_load_zi;
opcode ldzi_l mem_load_zi;
opcode ldzi_p mem_load_zi;
opcode ldzi_f mem_load_zi;
opcode ldzi_d mem_load_zi;
opcode ldzi2_b mem_load_zi;
opcode ldzi2_w mem_load_zi;
opcode ldzi2_l mem_load_zi;
opcode ldzi2_p mem_load_zi;
opcode ldzi2_f mem_load_zi;
opcode ldzi2_d mem_load_zi;
opcode ldri_b mem_load_ri;
opcode ldri_w mem_load_ri;
opcode ldri_l mem_load_ri;
opcode ldri_p mem_load_ri;
opcode ldri_f mem_load_ri;
opcode ldri_d mem_load_ri;
opcode ldri2_b mem_load_ri;
opcode ldri2_w mem_load_ri;
opcode ldri2_l mem_load_ri;
opcode ldri2_p mem_load_ri;
opcode ldri2_f mem_load_ri;
opcode ldri2_d mem_load_ri;
opcode ldrr_b mem_load_rr;
opcode ldrr_w mem_load_rr;
opcode ldrr_l mem_load_rr;
opcode ldrr_p mem_load_rr;
opcode ldrr_f mem_load_rr;
opcode ldrr_d mem_load_rr;
opcode ldrr2_b mem_load_rr;
opcode ldrr2_w mem_load_rr;
opcode ldrr2_l mem_load_rr;
opcode ldrr2_p mem_load_rr;
opcode ldrr2_f mem_load_rr;
opcode ldrr2_d mem_load_rr;
#
# unsigned byte and word load opcodes
#
opcode lduzi_b mem_load_zi;
opcode lduzi_w mem_load_zi;
opcode lduri_b mem_load_ri;
opcode lduri_w mem_load_ri;
opcode ldurr_b mem_load_rr;
opcode ldurr_w mem_load_rr;
opcode strzi_b mem_store_rzi;
opcode strzi_w mem_store_rzi;
opcode strzi_l mem_store_rzi;
opcode strzi_p mem_store_rzi;
opcode strzi_f mem_store_rzi;
opcode strzi_d mem_store_rzi;
opcode strzi2_b mem_store_rzi;
opcode strzi2_w mem_store_rzi;
opcode strzi2_l mem_store_rzi;
opcode strzi2_p mem_store_rzi;
opcode strzi2_f mem_store_rzi;
opcode strzi2_d mem_store_rzi;
opcode strri_b mem_store_rri;
opcode strri_w mem_store_rri;
opcode strri_l mem_store_rri;
opcode strri_p mem_store_rri;
opcode strri_f mem_store_rri;
opcode strri_d mem_store_rri;
opcode strri2_b mem_store_rri;
opcode strri2_w mem_store_rri;
opcode strri2_l mem_store_rri;
opcode strri2_p mem_store_rri;
opcode strri2_f mem_store_rri;
opcode strri2_d mem_store_rri;
opcode strrr_b mem_store_rrr;
opcode strrr_w mem_store_rrr;
opcode strrr_l mem_store_rrr;
opcode strrr_p mem_store_rrr;
opcode strrr_f mem_store_rrr;
opcode strrr_d mem_store_rrr;
opcode strrr2_b mem_store_rrr;
opcode strrr2_w mem_store_rrr;
opcode strrr2_l mem_store_rrr;
opcode strrr2_p mem_store_rrr;
opcode strrr2_f mem_store_rrr;
opcode strrr2_d mem_store_rrr;
opcode stizi_b mem_store_izi;
opcode stizi_w mem_store_izi;
opcode stizi_l mem_store_izi;
opcode stizi_p mem_store_izi;
opcode stizi_f mem_store_izi;
opcode stizi_d mem_store_izi;
opcode stizi2_b mem_store_izi;
opcode stizi2_w mem_store_izi;
opcode stizi2_l mem_store_izi;
opcode stizi2_p mem_store_izi;
opcode stizi2_f mem_store_izi;
opcode stizi2_d mem_store_izi;
opcode stiri_b mem_store_iri;
opcode stiri_w mem_store_iri;
opcode stiri_l mem_store_iri;
opcode stiri_p mem_store_iri;
opcode stiri_f mem_store_iri;
opcode stiri_d mem_store_iri;
opcode stiri2_b mem_store_iri;
opcode stiri2_w mem_store_iri;
opcode stiri2_l mem_store_iri;
opcode stiri2_p mem_store_iri;
opcode stiri2_f mem_store_iri;
opcode stiri2_d mem_store_iri;
opcode stirr_b mem_store_irr;
opcode stirr_w mem_store_irr;
opcode stirr_l mem_store_irr;
opcode stirr_p mem_store_irr;
opcode stirr_f mem_store_irr;
opcode stirr_d mem_store_irr;
opcode stirr2_b mem_store_irr;
opcode stirr2_w mem_store_irr;
opcode stirr2_l mem_store_irr;
opcode stirr2_p mem_store_irr;
opcode stirr2_f mem_store_irr;
opcode stirr2_d mem_store_irr;
# gen_opcode_wlfd(prefix,format)
# gen_opcode_wlf(prefix,format)
# gen_opcode_wl(prefix,format)
opcode mov_b : move unary_rr;
opcode mov_w : move unary_rr;
opcode mov_l : move unary_rr;
opcode mov_f : move unary_rr;
opcode mov_d : move unary_rr;
opcode movi_w unary_ir;
opcode movi_l unary_ir;
opcode movi_f unary_ir;
opcode movi_b : move unary_ir; # to support char assignment
opcode com_w unary_rr;
opcode com_l unary_rr;
opcode neg_w unary_rr;
opcode neg_l unary_rr;
opcode neg_f unary_rr;
opcode neg_d unary_rr;
opcode add_w binary_rrr;
opcode add_l binary_rrr;
opcode add_f binary_rrr;
opcode add_d binary_rrr;
opcode addi_w binary_rir;
opcode addi_l binary_rir;
opcode addi_f binary_rir;
opcode sub_w binary_rrr;
opcode sub_l binary_rrr;
opcode sub_f binary_rrr;
opcode sub_d binary_rrr;
opcode subi_w binary_rir;
opcode subi_l binary_rir;
opcode subi_f binary_rir;
opcode mul_w binary_rrr;
opcode mul_l binary_rrr;
opcode mul_f binary_rrr;
opcode mul_d binary_rrr;
opcode muli_w binary_rir;
opcode muli_l binary_rir;
opcode muli_f binary_rir;
opcode mulu_w binary_rrr;
opcode mulu_l binary_rrr;
opcode mului_w binary_rir;
opcode mului_l binary_rir;
opcode div_w binary_rrr;
opcode div_l binary_rrr;
opcode div_f binary_rrr;
opcode div_d binary_rrr;
opcode divi_w binary_rir;
opcode divi_l binary_rir;
opcode divi_f binary_rir;
opcode divu_w binary_rrr;
opcode divu_l binary_rrr;
opcode divui_w binary_rir;
opcode divui_l binary_rir;
opcode mod_w binary_rrr;
opcode mod_l binary_rrr;
opcode modi_w binary_rir;
opcode modi_l binary_rir;
opcode modu_w binary_rrr;
opcode modu_l binary_rrr;
opcode modui_w binary_rir;
opcode modui_l binary_rir;
opcode and_w binary_rrr;
opcode and_l binary_rrr;
opcode andi_w binary_rir;
opcode andi_l binary_rir;
opcode or_w binary_rrr;
opcode or_l binary_rrr;
opcode ori_w binary_rir;
opcode ori_l binary_rir;
opcode xor_w binary_rrr;
opcode xor_l binary_rrr;
opcode xori_w binary_rir;
opcode xori_l binary_rir;
opcode lls_w binary_rrr;
opcode lls_l binary_rrr;
opcode llsi_w binary_rir;
opcode llsi_l binary_rir;
opcode lrs_w binary_rrr;
opcode lrs_l binary_rrr;
opcode lrsi_w binary_rir;
opcode lrsi_l binary_rir;
opcode ars_w binary_rrr;
opcode ars_l binary_rrr;
opcode arsi_w binary_rir;
opcode arsi_l binary_rir;
opcode cmp_w compare_rr;
opcode cmp_l compare_rr;
opcode cmp_f compare_rr;
opcode cmp_d compare_rr;
opcode cmpu_w compare_rr;
opcode cmpu_l compare_rr;
opcode cmpi_w compare_ri;
opcode cmpi_l compare_ri;
opcode cmpui_w compare_ri;
opcode cmpui_l compare_ri;
opcode br : jump branch;
opcode call : call branch;
opcode beq : cjump branch;
opcode beq_f : cjump branch;
opcode bne : cjump branch;
opcode bne_f : cjump branch;
opcode ble : cjump branch;
opcode ble_u : cjump branch;
opcode ble_f : cjump branch;
opcode blt : cjump branch;
opcode blt_u : cjump branch;
opcode blt_f : cjump branch;
opcode bge : cjump branch;
opcode bge_u : cjump branch;
opcode bge_f : cjump branch;
opcode bgt : cjump branch;
opcode bgt_u : cjump branch;
opcode bgt_f : cjump branch;
opcode jmpind : jump brind;
opcode callind : call brind;
opcode ret : ret noargs;
opcode reti : ret noargs;
# cvt_opcode(type)
opcode cvtsbw unary_rr;
opcode cvtubw unary_rr;
opcode cvtsbl unary_rr;
opcode cvtubl unary_rr;
opcode cvtswl unary_rr;
opcode cvtuwl unary_rr;
opcode cvtlw unary_rr;
opcode cvtwf unary_rr;
opcode cvtuwf unary_rr;
opcode cvtlf unary_rr;
opcode cvtulf unary_rr;
opcode cvtdf unary_rr;
opcode cvtfw unary_rr;
opcode cvtfl unary_rr;
opcode cvtfd unary_rr;
opcode cvtwd unary_rr;
opcode cvtuwd unary_rr;
opcode cvtld unary_rr;
opcode cvtuld unary_rr;
opcode cvtdw unary_rr;
opcode cvtdl unary_rr;
opcode cvtlb unary_rr;
opcode cvtwb unary_rr;
opcode loopinit : cjump loopldr;
opcode loopiniti : cjump loopldi;
opcode loophead : cjump loop;
opcode loopend : cjump loop;
opcode looprpt : cjump loop;
opcode loopret noargs;
#
# C O D E T A B L E S
#
code binary(opcode,suffix)
? matches( $right, const16 )
{
opcode|"i_"|suffix $left,$right,$dest;
}
{
opcode|"_"|suffix $left,$right,$dest;
}
code unary(opcode,suffix)
? matches( $src, const16 )
{
opcode|"i_"|suffix $src,$dest;
}
{
opcode|"_"|suffix $src,$dest;
}
code unary_cast(opcode)
{
opcode $src,$dest;
}
#
# compiler-generated operations
#
# binary_int_oper(il_op,signed_mach_op,unsigned_mach_op)
# binary_float_oper(il_op,mach_op)
oper ADD : schar binary( "add", "w" );
oper ADD : uchar binary( "add", "w" );
oper ADD : sshort binary( "add", "w" );
oper ADD : ushort binary( "add", "w" );
oper ADD : slong binary( "add", "l" );
oper ADD : ulong binary( "add", "l" );
oper ADD : ptr binary("add", "l" );
oper ADD : codeptr binary("add", "l" );
oper ADD : float binary( "add", "f" );
oper ADD : double binary( "add", "d" );
oper SUB : schar binary( "sub", "w" );
oper SUB : uchar binary( "sub", "w" );
oper SUB : sshort binary( "sub", "w" );
oper SUB : ushort binary( "sub", "w" );
oper SUB : slong binary( "sub", "l" );
oper SUB : ulong binary( "sub", "l" );
oper SUB : ptr binary("sub", "l" );
oper SUB : float binary( "sub", "f" );
oper SUB : double binary( "sub", "d" );
oper MULT : schar binary( "mul", "w" );
oper MULT : uchar binary( "mulu", "w" );
oper MULT : sshort binary( "mul", "w" );
oper MULT : ushort binary( "mulu", "w" );
oper MULT : slong binary( "mul", "l" );
oper MULT : ulong binary( "mulu", "l" );
oper MULT : float binary( "mul", "f" );
oper MULT : double binary( "mul", "d" );
oper DIV : schar binary( "div", "w" );
oper DIV : uchar binary( "divu", "w" );
oper DIV : sshort binary( "div", "w" );
oper DIV : ushort binary( "divu", "w" );
oper DIV : slong binary( "div", "l" );
oper DIV : ulong binary( "divu", "l" );
oper DIV : float binary( "div", "f" );
oper DIV : double binary( "div", "d" );
oper REM : schar binary( "mod", "w" );
oper REM : uchar binary( "modu", "w" );
oper REM : sshort binary( "mod", "w" );
oper REM : ushort binary( "modu", "w" );
oper REM : slong binary( "mod", "l" );
oper REM : ulong binary( "modu", "l" );
oper LSHIFT : schar binary( "lls", "w" );
oper LSHIFT : uchar binary( "lls", "w" );
oper LSHIFT : sshort binary( "lls", "w" );
oper LSHIFT : ushort binary( "lls", "w" );
oper LSHIFT : slong binary( "lls", "l" );
oper LSHIFT : ulong binary( "lls", "l" );
oper RSHIFT : schar binary( "lrs", "w" );
oper RSHIFT : uchar binary( "lrs", "w" );
oper RSHIFT : sshort binary( "lrs", "w" );
oper RSHIFT : ushort binary( "lrs", "w" );
oper RSHIFT : slong binary( "lrs", "l" );
oper RSHIFT : ulong binary( "lrs", "l" );
oper ARSHFT : schar binary( "ars", "w" );
oper ARSHFT : uchar binary( "ars", "w" );
oper ARSHFT : sshort binary( "ars", "w" );
oper ARSHFT : ushort binary( "ars", "w" );
oper ARSHFT : slong binary( "ars", "l" );
oper ARSHFT : ulong binary( "ars", "l" );
oper AND : schar binary( "and", "w" );
oper AND : uchar binary( "and", "w" );
oper AND : sshort binary( "and", "w" );
oper AND : ushort binary( "and", "w" );
oper AND : slong binary( "and", "l" );
oper AND : ulong binary( "and", "l" );
oper OR : schar binary( "or", "w" );
oper OR : uchar binary( "or", "w" );
oper OR : sshort binary( "or", "w" );
oper OR : ushort binary( "or", "w" );
oper OR : slong binary( "or", "l" );
oper OR : ulong binary( "or", "l" );
oper EXOR : schar binary( "xor", "w" );
oper EXOR : uchar binary( "xor", "w" );
oper EXOR : sshort binary( "xor", "w" );
oper EXOR : ushort binary( "xor", "w" );
oper EXOR : slong binary( "xor", "l" );
oper EXOR : ulong binary( "xor", "l" );
oper UMINUS : sshort unary("neg", "w" );
oper UMINUS : ushort unary("neg", "w" );
oper UMINUS : slong unary("neg", "l" );
oper UMINUS : ulong unary("neg", "l" );
oper UMINUS : float unary("neg", "f" );
oper UMINUS : double unary("neg", "d" );
oper COMPL : sshort unary("com", "w" );
oper COMPL : ushort unary("com", "w" );
oper COMPL : slong unary("com", "l" );
oper COMPL : ulong unary("com", "l" );
code compare( opc, suffix )
? matches($right,const16)
{
opc|"i_"|suffix $left,$right;
}
{
opc|"_"|suffix $left,$right;
}
oper COMPARE : schar compare("cmp","w");
oper COMPARE : uchar compare("cmpu", "w");
oper COMPARE : sshort compare("cmp","w");
oper COMPARE : ushort compare("cmpu", "w");
oper COMPARE : slong compare("cmp","l");
oper COMPARE : ulong compare("cmpu", "l");
oper COMPARE : ptr compare("cmpu", "l");
oper COMPARE : codeptr compare("cmpu", "l");
oper COMPARE : float compare("cmp", "f" );
oper COMPARE : double compare("cmp", "d" );
#
# conversion operations are CAST_<from_type> : <to_type>
#
oper CAST_SCHAR : sshort unary_cast("cvtsbw");
oper CAST_SCHAR : ushort unary_cast("cvtsbw");
oper CAST_SCHAR : slong unary_cast("cvtsbl");
oper CAST_SCHAR : ulong unary_cast("cvtsbl");
oper CAST_UCHAR : sshort unary_cast("cvtubw");
oper CAST_UCHAR : ushort unary_cast("cvtubw");
oper CAST_UCHAR : slong unary_cast("cvtubl");
oper CAST_UCHAR : ulong unary_cast("cvtubl");
oper CAST_SSHORT : schar unary_cast("cvtwb");
oper CAST_SSHORT : uchar unary_cast("cvtwb");
oper CAST_SSHORT : slong unary_cast("cvtswl");
oper CAST_SSHORT : ulong unary_cast("cvtswl");
oper CAST_SSHORT : ptr unary_cast("cvtuwl");
oper CAST_SSHORT : ptr2 unary_cast("cvuswl");
oper CAST_SSHORT : float unary_cast("cvtwf");
oper CAST_SSHORT : double unary_cast("cvtwd");
oper CAST_USHORT : schar unary_cast("cvtwb");
oper CAST_USHORT : uchar unary_cast("cvtwb");
oper CAST_USHORT : slong unary_cast("cvtuwl");
oper CAST_USHORT : ulong unary_cast("cvtuwl");
oper CAST_USHORT : ptr unary_cast("cvtuwl");
oper CAST_USHORT : ptr2 unary_cast("cvuswl");
oper CAST_USHORT : float unary_cast("cvtuwf");
oper CAST_USHORT : double unary_cast("cvtuwd");
oper CAST_SLONG : schar unary_cast("cvtlb");
oper CAST_SLONG : uchar unary_cast("cvtlb");
oper CAST_SLONG : sshort unary_cast("cvtlw");
oper CAST_SLONG : ushort unary_cast("cvtlw");
oper CAST_SLONG : float unary_cast("cvtlf");
oper CAST_SLONG : double unary_cast("cvtld");
oper CAST_ULONG : schar unary_cast("cvtlb");
oper CAST_ULONG : uchar unary_cast("cvtlb");
oper CAST_ULONG : sshort unary_cast("cvtlw");
oper CAST_ULONG : ushort unary_cast("cvtlw");
oper CAST_ULONG : float unary_cast("cvtulf");
oper CAST_ULONG : double unary_cast("cvtuld");
oper CAST_FLOAT : sshort unary_cast("cvtfw");
oper CAST_FLOAT : ushort unary_cast("cvtfw");
oper CAST_FLOAT : slong unary_cast("cvtfl");
oper CAST_FLOAT : ulong unary_cast("cvtfl");
oper CAST_FLOAT : double unary_cast("cvtfd");
oper CAST_DOUBLE : sshort unary_cast("cvtdw");
oper CAST_DOUBLE : ushort unary_cast("cvtdw");
oper CAST_DOUBLE : slong unary_cast("cvtdl");
oper CAST_DOUBLE : ulong unary_cast("cvtdl");
oper CAST_DOUBLE : float unary_cast("cvtdf");
code asgn(suffix)
? in_reg_set($left,R) && matches($right,const16)
{
movi|"_"|suffix $right,$left;
$ASGN $nodest,$dest,$left;
}
? in_reg_set($left,R) && mem_ref($right)
{
$LOAD $left,$right;
$ASGN $nodest,$dest,$left;
}
? in_reg_set($left,R)
{
mov|"_"|suffix $right,$left;
$ASGN $nodest,$dest,$left;
}
? matches($left,zi_addr) && matches($right,const16)
{
stizi|"_"|suffix $right,$left;
$ASGN $nodest,$dest,$right;
}
? matches($left,zi_addr)
{
strzi|"_"|suffix $right,$left;
$ASGN $nodest,$dest,$right;
}
? matches($left,ri_addr) && matches($right,const16)
{
stiri|"_"|suffix $right,$left;
$ASGN $nodest,$dest,$right;
}
? matches($left,ri_addr)
{
strri|"_"|suffix $right,$left
$ASGN $nodest,$dest,$right
}
? matches($left,rr_addr) && matches($right,const16)
{
stirr|"_"|suffix $right,$left
$ASGN $nodest,$dest,$right
}
? matches($left,rr_addr)
{
strrr|"_"|suffix $right,$left
$ASGN $nodest,$dest,$right
}
? matches($right,const16)
{
stiri|"_"|suffix $right,$left
$ASGN $nodest,$dest,$right
}
{
strri|"_"|suffix $right,$left
$ASGN $nodest,$dest,$right
}
oper ASGN : schar asgn("b");
oper ASGN : uchar asgn("b");
oper ASGN : sshort asgn("w");
oper ASGN : ushort asgn("w");
oper ASGN : slong asgn("l");
oper ASGN : ulong asgn("l");
oper ASGN : ptr asgn("l");
oper ASGN : codeptr asgn("l");
oper ASGN : float asgn("f");
oper ASGN : double asgn("d");
code load(suffix)
? in_reg_set($left,R)
{
mov|"_"|suffix $left,$dest;
}
? matches($left,const16)
{
movi|"_"|suffix $left,$dest;
}
? matches($left,ri_addr)
{
ldri|"_"|suffix $left,$dest;
}
? matches($left,rr_addr)
{
ldrr|"_"|suffix $left,$dest;
}
? matches($left,zi_addr)
{
ldzi|"_"|suffix $left,$dest;
}
{
ldri|"_"|suffix $left,$dest;
}
code unsigned_load(suffix)
? in_reg_set($left,R)
{
mov|"_"|suffix $left,$dest;
}
? matches($left,const16)
{
movi|"_"|suffix $left,$dest;
}
? matches($left,ri_addr)
{
lduri|"_"|suffix $left,$dest;
}
? matches($left,rr_addr)
{
ldurr|"_"|suffix $left,$dest;
}
? matches($left,zi_addr)
{
lduzi|"_"|suffix $left,$dest;
}
{
lduri|"_"|suffix $left,$dest;
}
oper LOAD : schar load("b");
oper LOAD : uchar unsigned_load("b");
oper LOAD : sshort load("w");
oper LOAD : ushort unsigned_load("w");
oper LOAD : slong load("l");
oper LOAD : ulong load("l");
oper LOAD : codeptr load("l");
oper LOAD : ptr load("l");
oper LOAD : float load("f");
oper LOAD : double load("d");
code opasgn( opcode, suffix )
? in_reg_set($left,R) && matches($right,const16)
{
opcode|"i_"|suffix $left,$right,$left;
$ASGN $nodest,$dest,$left;
}
? in_reg_set($left,R)
{
opcode|"_"|suffix $left,$right,$left;
$ASGN $nodest,$dest,$left;
}
? mem_ref($left) && matches($right,const16)
{
$LOAD $tempreg,$left;
opcode|"i_"|suffix $tempreg,$right,$tempreg;
$ASGN $nodest,$left,$tempreg;
$ASGN $nodest,$dest,$tempreg;
}
{
$LOAD $tempreg,$left;
opcode|"_"|suffix $tempreg,$right,$tempreg;
$ASGN $nodest,$left,$tempreg;
$ASGN $nodest,$dest,$tempreg;
}
#opasgn_integral(il_op,mach_op,uns_mach_op)
# must include char and schar types
#
#opasgn_float(il_op,mach_op)
oper ADDEQ : schar opasgn("add","w");
oper ADDEQ : uchar opasgn("add","w");
oper ADDEQ : sshort opasgn("add","w");
oper ADDEQ : ushort opasgn("add","w");
oper ADDEQ : slong opasgn("add","l");
oper ADDEQ : ulong opasgn("add","l");
oper ADDEQ : ptr opasgn("add","l");
oper ADDEQ : float opasgn("add","f");
oper ADDEQ : double opasgn("add","d");
oper PREINC : schar opasgn("add","w");
oper PREINC : uchar opasgn("add","w");
oper PREINC : sshort opasgn("add","w");
oper PREINC : ushort opasgn("add","w");
oper PREINC : slong opasgn("add","l");
oper PREINC : ulong opasgn("add","l");
oper PREINC : ptr opasgn("add","l");
oper PREINC : float opasgn("add","f");
oper PREINC : double opasgn("add","d");
oper SUBEQ : schar opasgn("sub","w");
oper SUBEQ : uchar opasgn("sub","w");
oper SUBEQ : sshort opasgn("sub","w");
oper SUBEQ : ushort opasgn("sub","w");
oper SUBEQ : slong opasgn("sub","l");
oper SUBEQ : ulong opasgn("sub","l");
oper SUBEQ : ptr opasgn("sub","l");
oper SUBEQ : float opasgn("sub","f");
oper SUBEQ : double opasgn("sub","d");
oper PREDEC : schar opasgn("sub","w");
oper PREDEC : uchar opasgn("sub","w");
oper PREDEC : sshort opasgn("sub","w");
oper PREDEC : ushort opasgn("sub","w");
oper PREDEC : slong opasgn("sub","l");
oper PREDEC : ulong opasgn("sub","l");
oper PREDEC : ptr opasgn("sub","l");
oper PREDEC : float opasgn("sub","f");
oper PREDEC : double opasgn("sub","d");
oper MULEQ : schar opasgn("mul","w");
oper MULEQ : uchar opasgn("mulu","w");
oper MULEQ : sshort opasgn("mul","w");
oper MULEQ : ushort opasgn("mulu","w");
oper MULEQ : slong opasgn("mul","l");
oper MULEQ : ulong opasgn("mulu","l");
oper MULEQ : float opasgn("mul","f");
oper MULEQ : double opasgn("mul","d");
oper DIVEQ : schar opasgn("div","w");
oper DIVEQ : uchar opasgn("divu","w");
oper DIVEQ : sshort opasgn("div","w");
oper DIVEQ : ushort opasgn("divu","w");
oper DIVEQ : slong opasgn("div","l");
oper DIVEQ : ulong opasgn("divu","l");
oper DIVEQ : float opasgn("div","f");
oper DIVEQ : double opasgn("div","d");
oper REMEQ : schar opasgn("mod","w");
oper REMEQ : uchar opasgn("modu","w");
oper REMEQ : sshort opasgn("mod","w");
oper REMEQ : ushort opasgn("modu","w");
oper REMEQ : slong opasgn("mod","l");
oper REMEQ : ulong opasgn("modu","l");
oper ANDEQ : schar opasgn("and","w");
oper ANDEQ : uchar opasgn("and","w");
oper ANDEQ : sshort opasgn("and","w");
oper ANDEQ : ushort opasgn("and","w");
oper ANDEQ : slong opasgn("and","l");
oper ANDEQ : ulong opasgn("and","l");
oper OREQ : schar opasgn("or","w");
oper OREQ : uchar opasgn("or","w");
oper OREQ : sshort opasgn("or","w");
oper OREQ : ushort opasgn("or","w");
oper OREQ : slong opasgn("or","l");
oper OREQ : ulong opasgn("or","l");
oper EXOREQ : schar opasgn("xor","w");
oper EXOREQ : uchar opasgn("xor","w");
oper EXOREQ : sshort opasgn("xor","w");
oper EXOREQ : ushort opasgn("xor","w");
oper EXOREQ : slong opasgn("xor","l");
oper EXOREQ : ulong opasgn("xor","l");
oper LSHEQ : schar opasgn("lls","w");
oper LSHEQ : uchar opasgn("lls","w");
oper LSHEQ : sshort opasgn("lls","w");
oper LSHEQ : ushort opasgn("lls","w");
oper LSHEQ : slong opasgn("lls","l");
oper LSHEQ : ulong opasgn("lls","l");
oper RSHEQ : schar opasgn("lrs","w");
oper RSHEQ : uchar opasgn("lrs","w");
oper RSHEQ : sshort opasgn("lrs","w");
oper RSHEQ : ushort opasgn("lrs","w");
oper RSHEQ : slong opasgn("lrs","l");
oper RSHEQ : ulong opasgn("lrs","l");
oper ARSEQ : schar opasgn("ars","w");
oper ARSEQ : uchar opasgn("ars","w");
oper ARSEQ : sshort opasgn("ars","w");
oper ARSEQ : ushort opasgn("ars","w");
oper ARSEQ : slong opasgn("ars","l");
oper ARSEQ : ulong opasgn("ars","l");
code branch_code(opcode)
{
opcode $left;
}
code op_noargs(opcode)
{
opcode;
}
code op_null
{
}
code op_enter
? matches($left,constz)
{
addi_l $reg(R[31]),4,$reg(R[31]); # advance sp to make room for prev fp
$ASGN : ulong $nodest,
$mktree(*($reg(R[31]) : ptr ulong -1)),$reg(R[30]); # save prev fp
mov_l $reg(R[31]),$reg(R[30]); # fp = sp
}
{
addi_l $reg(R[31]),4,$reg(R[31]); # advance sp to make room for prev fp
$ASGN : ulong $nodest,
$mktree(*($reg(R[31]) : ptr ulong -1)),$reg(R[30]); # save prev fp
mov_l $reg(R[31]),$reg(R[30]); # fp = sp
$ADD : ulong $reg(R[31]),$reg(R[31]),$left; # sp += framesize
}
code op_exit
{
mov_l $reg(R[30]),$reg(R[31]); # sp = fp
$ASGN : ulong $nodest,$reg(R[30]),
$mktree(*($reg(R[31]) : ptr ulong - 1)); # fp = *(sp - 4)
subi_l $reg(R[31]),4,$reg(R[31]); # backup sp over prev fp
}
oper CALLDIR : void branch_code("call");
oper CALLIND : void branch_code("callind");
oper JUMP : void branch_code("br");
oper JUMPIND : void branch_code("jmpind");
oper RET : void op_noargs("ret");
oper RETI : void op_noargs("reti");
oper EXIT : void op_exit;
oper EXITI : void op_exit;
oper ENTER : void op_enter;
oper ENTERI : void op_enter;
#br_op(il_op,mach_op,uns_mach_op,float_op)
oper BREQ : schar branch_code(beq);
oper BREQ : uchar branch_code(beq);
oper BREQ : sshort branch_code(beq);
oper BREQ : ushort branch_code(beq);
oper BREQ : slong branch_code(beq);
oper BREQ : ulong branch_code(beq);
oper BREQ : codeptr branch_code(beq);
oper BREQ : ptr branch_code(beq);
oper BREQ : float branch_code(beq_f);
oper BREQ : double branch_code(beq_f);
oper BRNE : schar branch_code(bne);
oper BRNE : uchar branch_code(bne);
oper BRNE : sshort branch_code(bne);
oper BRNE : ushort branch_code(bne);
oper BRNE : slong branch_code(bne);
oper BRNE : ulong branch_code(bne);
oper BRNE : codeptr branch_code(bne);
oper BRNE : ptr branch_code(bne);
oper BRNE : float branch_code(bne_f);
oper BRNE : double branch_code(bne_f);
oper BRLT : schar branch_code(blt);
oper BRLT : uchar branch_code(blt_u);
oper BRLT : sshort branch_code(blt);
oper BRLT : ushort branch_code(blt_u);
oper BRLT : slong branch_code(blt);
oper BRLT : ulong branch_code(blt_u);
oper BRLT : codeptr branch_code(blt_u);
oper BRLT : ptr branch_code(blt_u);
oper BRLT : float branch_code(blt_f);
oper BRLT : double branch_code(blt_f);
oper BRLE : schar branch_code(ble);
oper BRLE : uchar branch_code(ble_u);
oper BRLE : sshort branch_code(ble);
oper BRLE : ushort branch_code(ble_u);
oper BRLE : slong branch_code(ble);
oper BRLE : ulong branch_code(ble_u);
oper BRLE : codeptr branch_code(ble_u);
oper BRLE : ptr branch_code(ble_u);
oper BRLE : float branch_code(ble_f);
oper BRLE : double branch_code(ble_f);
oper BRGT : schar branch_code(bgt);
oper BRGT : uchar branch_code(bgt_u);
oper BRGT : sshort branch_code(bgt);
oper BRGT : ushort branch_code(bgt_u);
oper BRGT : slong branch_code(bgt);
oper BRGT : ulong branch_code(bgt_u);
oper BRGT : codeptr branch_code(bgt_u);
oper BRGT : ptr branch_code(bgt_u);
oper BRGT : float branch_code(bgt_f);
oper BRGT : double branch_code(bgt_f);
oper BRGE : schar branch_code(bge);
oper BRGE : uchar branch_code(bge_u);
oper BRGE : sshort branch_code(bge);
oper BRGE : ushort branch_code(bge_u);
oper BRGE : slong branch_code(bge);
oper BRGE : ulong branch_code(bge_u);
oper BRGE : codeptr branch_code(bge_u);
oper BRGE : ptr branch_code(bge_u);
oper BRGE : float branch_code(bge_f);
oper BRGE : double branch_code(bge_f);
code post_op(opcode,suffix)
? in_reg_set($left,R) && matches($right,const16)
{
$LOAD $dest,$left
opcode|"i_"|suffix $left,$right,$left
}
? in_reg_set($left,R)
{
$LOAD $dest,$left
opcode|"_"|suffix $left,$right,$left
}
? matches($right,const16)
{
$LOAD $temp,$left
opcode|"i_"|suffix $temp,$right,$temp2
$ASGN $nodest,$left,$temp2
$ASGN $nodest,$dest,$temp
}
{
$LOAD $temp,$left
opcode|"_"|suffix $temp,$right,$temp2
$ASGN $nodest,$left,$temp2
$ASGN $nodest,$dest,$temp
}
oper POSTINC : schar post_op(add,w);
oper POSTINC : uchar post_op(add,w);
oper POSTINC : sshort post_op(add,w);
oper POSTINC : ushort post_op(add,w);
oper POSTINC : slong post_op(add,l);
oper POSTINC : ulong post_op(add,l);
oper POSTINC : ptr post_op(add,l);
oper POSTINC : float post_op(add,f);
oper POSTINC : double post_op(add,d);
oper POSTDEC : schar post_op(sub,w);
oper POSTDEC : uchar post_op(sub,w);
oper POSTDEC : sshort post_op(sub,w);
oper POSTDEC : ushort post_op(sub,w);
oper POSTDEC : slong post_op(sub,l);
oper POSTDEC : ulong post_op(sub,l);
oper POSTDEC : ptr post_op(sub,l);
oper POSTDEC : float post_op(sub,f);
oper POSTDEC : double post_op(sub,d);
code loopld(opcode)
? matches($left,const16)
{
opcode|i $left,$right;
}
{
opcode $left,$right;
}
code loopcode(opcode)
{
opcode $left,$right;
}
oper LOOPINIT : void loopld(loopinit);
oper LOOPRET : void op_noargs(loopret);
oper LOOPHEAD : void loopcode(loophead);
oper LOOPRPT : void loopcode(looprpt);
oper LOOPEND : void loopcode(loopend);
#
# this code is used when the compiler
# loads a structure into a register,
# such as when passing a structure argument in a register
# or assigning a structure in memory to a structure in registers.
#
code structload
? tsize($left) == 4 && in_reg_set($dest,R)
{
$LOAD : ulong $dest,$left
}
? tsize($left) == 8 && in_reg_set($dest,R)
{
$LOAD : double $dest,$left
}
? tsize($left) == 12 && in_reg_set($dest,R)
{
$LOAD : double $dest.sel(0,1),$left.offset(0)
$LOAD : ulong $dest.sel(2,2),$left.offset(4)
}
? tsize($left) == 16 && in_reg_set($dest,R)
{
$LOAD : double $dest.msb,$left.offset(0)
$LOAD : double $dest.lsb,$left.offset(4)
}
{
$err "Unexpected condition in structload, tsize = ",
$mkconst(tsize($left))
}
oper LOAD : struct structload;
code blkmove
? tsize($left) == 4
{
$ASGN : ulong $nodest,$left,$right;
$ADDR $dest,$left;
}
? tsize($left) == 8
{
$ASGN : double $nodest,$left,$right;
$ADDR $dest,$left;
}
? tsize($left)%4 == 0
{
$LABEL looptop;
$LABEL loopend;
$ADDR $leftaddr : ptr ulong,$left;
$ADDR $rightaddr : ptr ulong,$right;
$LOOPINIT : void $nodest,$mkconst( tsize($left)>>2 ),loopend;
looptop:
$LOOPHEAD : void $nodest,looptop,loopend;
$LOAD : slong $temp,$mktree(*$rightaddr);
addi_l $rightaddr,$mkconst(4),$rightaddr;
$ASGN : slong $nodest,$mktree(*$leftaddr),$temp;
addi_l $leftaddr,$mkconst(4),$leftaddr;
$LOOPRPT : void $nodest,looptop,loopend;
loopend:
$LOOPEND : void $nodest,looptop,loopend;
$SUB : ulong $dest,$leftaddr,$mkconst(tsize($left));
}
{
$LABEL looptop;
$LABEL loopend;
$ADDR $leftaddr : ptr uchar,$left;
$ADDR $rightaddr : ptr uchar,$right;
$LOOPINIT : void $nodest,$mkconst( tsize($left) ),loopend;
looptop:
$LOOPHEAD : void $nodest,looptop,loopend;
$LOAD : uchar $temp,$mktree(*$rightaddr);
addi_l $rightaddr,$mkconst(1),$rightaddr;
$ASGN : uchar $nodest,$mktree(*$leftaddr),$temp;
addi_l $leftaddr,$mkconst(1),$leftaddr;
$LOOPRPT : void $nodest,looptop,loopend;
loopend:
$LOOPEND : void $nodest,looptop,loopend;
$SUB : ulong $dest,$leftaddr,$mkconst(tsize($left));
}
oper BLKMOV : struct blkmove;
opcode output_b output;
opcode output_w output;
opcode output_l output;
opcode output_f output;
opcode output_d output;
opcode outputi_b outputi;
opcode outputi_w outputi;
opcode outputi_l outputi;
code output(opcode,suffix)
? matches( $right, const16 ) && matches( $left, const16 )
{
opcode|"i_"|suffix $left,$right;
$ASGN $nodest,$dest,$right
}
? matches( $left, const16 )
{
opcode|"_"|suffix $left,$right;
$ASGN $nodest,$dest,$right
}
{
$err "First arg to output must be constant"
}
oper boutput : schar output("output","b");
oper soutput : sshort output("output","w");
oper output : sshort output("output","w");
oper loutput : slong output("output","l");
oper foutput : float output("output","f");
oper doutput : double output("output","d");
Back to Archelon's Home Page