Archelon Ischyros Archelon Inc.

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;
regset := R[32] width=32
scratch := R[24-27];
argreg := R[24-27];
color := R[0-29];
    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;

# must include char and schar types


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)

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;


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 = ",

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;
    $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 : 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;
    $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 : 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