The compiler generates instructions using code tables which you provide in a text file, called the Compiler Information File (CIF). This file describes the instructions of your machine and tells the compiler how to generate code for it. The information in the file includes descriptions of:
The file content shown below contains macros which must be expanded (using the widely available m4 macro preprocessor) to generate a CIF file for either the TMS320C30 or the TMS320C40 processor family.
For more information about the CIF, see the Technical Overview.You can reach us by email at info@archelon.com.
# @(#) c3x.cs 1.37 01/10/12 22:05:07 @(#) # # CIF files for the C3X and C4X # # Copyright (c) 1996-98, 2001 Archelon Inc. All Rights Reserved. # ifdef( `CPU', `', `define(`CPU', `C3X')' ) ifelse( CPU, `C3X', `define( `GPRS', `8' )', `define( `GPRS', `12' )') ifelse( CPU, `C3X', `define( `LAST_GPR', `7' )', `define( `LAST_GPR', `11' )') rom_init; one_mem; mau := 32; code_locinc := 1; data_locinc := 1; int := long; char := signed; wchar := long; data_pointer := long; code_pointer := long; double := float; cost leaf = 0; var push_size; var frame_size; # define macros to prevent floating point from being # converted to IEEE format by the compiler # because the C3x uses its own special floating point format. expansion fmtf "\%f"; expansion fmtd "\%f"; expansion dataf "\tdef_float %1%n"; expansion datad "\tdef_double %1%n"; ### # The lowest numbered register set with scratch registers is used for # the return value from a function. Thus the order in which register # sets are declared is significant. # Extended-Precision Registers # Stores either 32-bit integer or 40-bit floating point values. # # Float Format: # 39:32 e Exponent # 31 s Sign # 30:0 f Fraction # # Integer Format: # 39:32 unchanged # 31:0 signed/unsigned integer # # we declare these as 64-bits wide, to allow the compiler # to do magical things when spilling and unspilling them regset := R[ GPRS ] width = 64 optype = int regtype = char, short, int, long, float expansion R = "r%2" ; # Auxiliary Registers regset := AR[8] width = 32 optype = int, ptr regtype = char, short, int, long, ptr, codeptr expansion AR = "ar%2" ; # Data Page Pointer # 31:8 Reserved - always set 0 # 7:0 Page number of 64K words. regset := DP width = 32 optype = int regtype = int, long expansion DP = "dp" ; # Index Registers regset := IR[2] width = 32 optype = int regtype = int, long expansion IR = "ir%2" ; # Block-Size Register regset := BK width = 32 optype = int regtype = int, long expansion BK = "bk" ; # Status Register # 31:16 Reserved - undefined # 15:14 Reserved - always reads 0 # 13 GIE Global Interrupt Enable # 12 CC Cache Clear - write 1 invalidates caches, always reads 0. # 11 CE Cache Enable # 10 CF Cache Freeze # 9 Reserved - always reads 0 # 8 RM Repeat Mode flag # 7 OVM Overflow Mode flag # 6 LUF Latched floating point underflow flag. # 5 LV Latched overflow flag # 4 UF Floating point under flow. # 3 N Negative flag # 2 Z Zero flag # 1 V Overflow flag # 0 C Carry/barrow flag regset := ST width = 32 optype = int regtype = int, long expansion ST = "st" ; # CPU/DMA Interrupt Enable Register # 10:0 CPU interrupt enable bits # 26:16 DMA interrupt enablea bits regset := IE width = 32 optype = int regtype = int, long expansion IE = "ie" ; # CPU Interrupt Flag Register regset := IF width = 32 optype = int regtype = int, long expansion IF = "if" ; # I/O Flags Register regset := IOF width = 32 optype = int regtype = int, long expansion IOF = "iof" ; # Repeat Counter regset := RC width = 32 optype = int regtype = int, long expansion RC = "rc" ; # Repeat Start Address Register regset := RS width = 32 optype = codeptr regtype = codeptr expansion RS = "rs" ; # Repeat End Address Register regset := RE width = 32 optype = codeptr regtype = codeptr expansion RE = "re" ; # Stack Pointer # Always points to the last element pushed onto the stack. regset := SP width = 32 optype = ptr regtype = ptr expansion SP = "sp" ; # Condition Codes define( `MAX_CC', `7' ) define( `CC_C', `0' ) define( `CC_V', `1' ) define( `CC_Z', `2' ) define( `CC_N', `3' ) define( `CC_UF', `4' ) define( `CC_LV', `5' ) define( `CC_LUF', `6' ) define( `CC_ALL', `CC[0], CC[1], CC[2], CC[3], CC[4], CC[5], CC[6]' ) regset := CC [ MAX_CC ] width = 1; spill writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); copy writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); # Two machine words saved on stack : return address and frame pointer. # The return address is pushed implicitly on the call # and popped implicitly on the return; # the frame pointer is pushed and popped explicitly by our # enter and exit code, and is therefore not accounted for here stack push_args, no_stack_init, low_to_high, stkptr := SP, frameptr := AR[7], hw_farg_offset := 1, hw_lauto_offset := 1, push_pre_mod ; argreg := R[ 0 - 1 ]; argreg := AR[ 0 - 1 ]; scratch := R[ 0 - 4 ]; scratch := AR[ 0 - 4 ]; scratch := IR[ 0 - 1 ]; color := IR[ 0 - 1 ]; color := R[ 0 - LAST_GPR ]; color := AR[ 0 - 6 ]; define( `SCRATCHES', `writes( R[0], R[1], R[2], R[3], R[4], AR[0], AR[1], AR[2], AR[3], AR[4], IR[0], IR[1] )' ) ### Operands operand R reg R; operand AR reg AR; operand IX reg IR; #note that we use IX, not IR */ operand BK reg BK; operand DP reg DP; operand IE reg IE; operand IF reg IF; operand IOF reg IOF; operand RC reg RC; operand RE reg RE; operand RS reg RS; operand ST reg ST; operand SP reg SP; operand zero uconst 0; operand pos_one uconst 1; operand neg_one sconst -1; operand p8 uconst 0 0xff; operand m8 sconst -0xff -1; operand u16 uconst 0 0xffff; operand s16 sconst -0x7fff 0x7fff; operand u32 uconst 0 0xffffffff; operand s32 sconst -0x7fffffff 0x7fffffff; operand f16 fconst -2.5600e2 2.5594e2; operand f32 fconst -3.4028236e38 3.4028234e38; operand f40 fconst -3.4028236691e38 3.4028236683e38; operand data ptr; operand code codeptr; # NOTE that direct addressing specifies the LSB 16 bits as part # of the operand and that MSB are put into the page register. operand addr amode data expansion "@%2"; operand ldp_addr amode data expansion "%2"; # Indirect and implied displacement of zero. operand ind amode AR expansion "*%1"; # Indirect and implied displacement of one. operand pos_1 amode AR + pos_one expansion "*+%1(0x1)"; operand neg_1 amode AR + neg_one expansion "*-%1(0x1)"; # Indirect and displacement. operand pos_n amode AR + p8 expansion "*+%1(%2)"; operand neg_n amode AR + m8 expansion "*-%1(-%2)"; # Indirect and index. operand ind_ix amode AR + IR expansion "*+%1(%3)"; # Indirect and implied adjustment of one. operand preinc amode ++ 1 AR expansion "*++%1"; operand predec amode -- 1 AR expansion "*--%1"; operand postinc amode AR ++ 1 expansion "*%1++"; operand postdec amode AR -- 1 expansion "*%1--"; ### Formats and Opcodes format noargs; opcode idle noargs; opcode nop noargs; opcode sigi noargs; opcode swi noargs; # Always opcode retiu : ret noargs; # Equality opcode retieq : ret noargs reads( CC[CC_Z] ); opcode retine : ret noargs reads( CC[CC_Z] ); # Unsigned compare. opcode retilo : ret noargs reads( CC[CC_C] ); opcode retils : ret noargs reads( CC[CC_C], CC[CC_Z] ); opcode retihi : ret noargs reads( CC[CC_C], CC[CC_Z] ); opcode retihs : ret noargs reads( CC[CC_C] ); # Signed compare. opcode retilt : ret noargs reads( CC[CC_N] ); opcode retile : ret noargs reads( CC[CC_N], CC[CC_Z] ); opcode retigt : ret noargs reads( CC[CC_N], CC[CC_Z] ); opcode retige : ret noargs reads( CC[CC_N] ); # Condition flags. opcode retic : ret noargs reads( CC[CC_C] ); opcode retinc : ret noargs reads( CC[CC_C] ); opcode retiz : ret noargs reads( CC[CC_Z] ); opcode retinz : ret noargs reads( CC[CC_Z] ); opcode retiv : ret noargs reads( CC[CC_V] ); opcode retinv : ret noargs reads( CC[CC_V] ); opcode retiuf : ret noargs reads( CC[CC_UF] ); opcode retinuf : ret noargs reads( CC[CC_UF] ); opcode retilv : ret noargs reads( CC[CC_LV] ); opcode retinlv : ret noargs reads( CC[CC_LV] ); opcode retiluf : ret noargs reads( CC[CC_LUF] ); opcode retinluf : ret noargs reads( CC[CC_LUF] ); opcode retizuf : ret noargs reads( CC[CC_Z], CC[CC_UF] ); # Always opcode retsu : ret noargs; # Equality opcode retseq : ret noargs reads( CC[CC_Z] ); opcode retsne : ret noargs reads( CC[CC_Z] ); # Unsigned compare. opcode retslo : ret noargs reads( CC[CC_C] ); opcode retsls : ret noargs reads( CC[CC_C], CC[CC_Z] ); opcode retshi : ret noargs reads( CC[CC_C], CC[CC_Z] ); opcode retshs : ret noargs reads( CC[CC_C] ); # Signed compare. opcode retslt : ret noargs reads( CC[CC_N] ); opcode retsle : ret noargs reads( CC[CC_N], CC[CC_Z] ); opcode retsgt : ret noargs reads( CC[CC_N], CC[CC_Z] ); opcode retsge : ret noargs reads( CC[CC_N] ); # Condition flags. opcode retsc : ret noargs reads( CC[CC_C] ); opcode retsnc : ret noargs reads( CC[CC_C] ); opcode retsz : ret noargs reads( CC[CC_Z] ); opcode retsnz : ret noargs reads( CC[CC_Z] ); opcode retsv : ret noargs reads( CC[CC_V] ); opcode retsnv : ret noargs reads( CC[CC_V] ); opcode retsuf : ret noargs reads( CC[CC_UF] ); opcode retsnuf : ret noargs reads( CC[CC_UF] ); opcode retslv : ret noargs reads( CC[CC_LV] ); opcode retsnlv : ret noargs reads( CC[CC_LV] ); opcode retsluf : ret noargs reads( CC[CC_LUF] ); opcode retsnluf : ret noargs reads( CC[CC_LUF] ); opcode retszuf : ret noargs reads( CC[CC_Z], CC[CC_UF] ); # immediate values are sign-extended format ea_r src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; # immediate values are NOT sign-extended format ea_r_n src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | u16 | pos_n | neg_n | ind_ix | ind dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode absi ea_r writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode negb ea_r writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode negi ea_r writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode not ea_r_n writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode negf ea_r writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode norm ea_r writes( CC[CC_LUF], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode rnd ea_r writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); # immediate values are sign-extended format ea_r_2 rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind lsrcdest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; # immediate values are NOT sign-extended format ea_r_2n rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | u16 | pos_n | neg_n | ind_ix | ind lsrcdest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode addc ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addi ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subb ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subi ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode mpyi ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode andn ea_r_2n writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode and ea_r_2n writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode or ea_r_2n writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode xor ea_r_2n writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); # If src shift count >= 0, then # left shift by count, # else # right shift by -count. opcode ash ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode lsh ea_r_2 writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); # We use the same format for the floating point instructions, relying on the # fact that register set R is the only possible match for a float register. opcode addf ea_r_2 writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode subf ea_r_2 writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyf ea_r_2 writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format cmp_ea_r_2 lsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; # opcodes to do comparisons opcode cmpi : compare cmp_ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpi_da : compare cmp_ea_r_2 writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpf : compare cmp_ea_r_2 writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format rrr lsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format irr lsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format rir lsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP rsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format iir lsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind rsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode addc_rrr expansion "\taddc3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addc_irr expansion "\taddc3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addc_rir expansion "\taddc3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addc_iir expansion "\taddc3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addi_rrr expansion "\taddi3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addi_irr expansion "\taddi3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addi_rir expansion "\taddi3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addi_iir expansion "\taddi3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subb_rrr expansion "\tsubb3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subb_irr expansion "\tsubb3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subb_rir expansion "\tsubb3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subb_iir expansion "\tsubb3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subi_rrr expansion "\tsubi3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subi_irr expansion "\tsubi3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subi_rir expansion "\tsubi3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode subi_iir expansion "\tsubi3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode mpyi_rrr expansion "\tmpyi3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyi_irr expansion "\tmpyi3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyi_rir expansion "\tmpyi3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyi_iir expansion "\tmpyi3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode andn_rrr expansion "\tandn3 %3%5\n" rrr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode andn_irr expansion "\tandn3 %3%5\n" irr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode andn_rir expansion "\tandn3 %3%5\n" rir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode andn_iir expansion "\tandn3 %3%5\n" iir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode and_rrr expansion "\tand3 %3%5\n" rrr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode and_irr expansion "\tand3 %3%5\n" irr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode and_rir expansion "\tand3 %3%5\n" rir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode and_iir expansion "\tand3 %3%5\n" iir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode or_rrr expansion "\tor3 %3%5\n" rrr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode or_irr expansion "\tor3 %3%5\n" irr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode or_rir expansion "\tor3 %3%5\n" rir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode or_iir expansion "\tor3 %3%5\n" iir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode xor_rrr expansion "\txor3 %3%5\n" rrr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode xor_irr expansion "\txor3 %3%5\n" irr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode xor_rir expansion "\txor3 %3%5\n" rir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode xor_iir expansion "\txor3 %3%5\n" iir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode ash_rrr expansion "\tash3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode ash_irr expansion "\tash3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode ash_rir expansion "\tash3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode ash_iir expansion "\tash3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode lsh_rrr expansion "\tlsh3 %3%5\n" rrr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode lsh_irr expansion "\tlsh3 %3%5\n" irr writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode lsh_rir expansion "\tlsh3 %3%5\n" rir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode lsh_iir expansion "\tlsh3 %3%5\n" iir writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode addf_rrr expansion "\taddf3 %3%5\n" rrr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode addf_irr expansion "\taddf3 %3%5\n" irr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode addf_rir expansion "\taddf3 %3%5\n" rir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode addf_iir expansion "\taddf3 %3%5\n" iir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode subf_rrr expansion "\tsubf3 %3%5\n" rrr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode subf_irr expansion "\tsubf3 %3%5\n" irr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode subf_rir expansion "\tsubf3 %3%5\n" rir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode subf_iir expansion "\tsubf3 %3%5\n" iir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyf_rrr expansion "\tmpyf3 %3%5\n" rrr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyf_irr expansion "\tmpyf3 %3%5\n" irr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyf_rir expansion "\tmpyf3 %3%5\n" rir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode mpyf_iir expansion "\tmpyf3 %3%5\n" iir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format cmp_rrr lsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format cmp_irr lsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format cmp_rir lsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP rsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind ; format cmp_iir lsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind rsrc pos_1 | neg_1 | ind_ix | preinc | predec | postinc | postdec | ind ; opcode cmpi_rrr : compare expansion "\tcmpi3 %3%5\n" rrr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpi_irr : compare expansion "\tcmpi3 %3%5\n" irr writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpi_rir : compare expansion "\tcmpi3 %3%5\n" rir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpi_iir : compare expansion "\tcmpi3 %3%5\n" iir writes( CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode cmpf_rrr : compare expansion "\tcmpf3 %3%5\n" rrr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode cmpf_irr : compare expansion "\tcmpf3 %3%5\n" irr writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode cmpf_rir : compare expansion "\tcmpf3 %3%5\n" rir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode cmpf_iir : compare expansion "\tcmpf3 %3%5\n" iir writes( CC[CC_LUF], CC[CC_LV], CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format ld_cond expansion "%1 %2, %3" string zero rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind lsrcdest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode ldi_cond expansion "\tldi%3%5\n" ld_cond reads( CC_ALL ); opcode ldf_cond expansion "\tldf%3%5\n" ld_cond reads( CC_ALL ); format ld_ea_ri src R | s16 | s32 | u32 | addr | pos_n | neg_n | ind_ix | ind | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format ld_ea_rf src R | s16 | s32 | u32 | addr | pos_n | neg_n | ind_ix | ind | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP dest R ; ifelse( CPU, `C3X', `', `opcode ldhi ld_ea_ri;' ) opcode ldi ld_ea_ri writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode lde ld_ea_rf; opcode ldf ld_ea_rf writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode ldm ld_ea_rf; format ld_imm src u32 | s32 dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode upper expansion "\tldp %3%5\n" ld_imm; opcode lower expansion "\tldi %3%5\n" ld_imm writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format move src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode movei : nse expansion "\tldi %3%5\n" move writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode moveim : move expansion "\tldi %3%5\n" move writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode movef : nse expansion "\tldfu %3%5\n" move writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode movefm : move expansion "\tldfu %3%5\n" move writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format r_ea_2 rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP lsrc addr | pos_n | neg_n | ind_ix | ind ; opcode sti r_ea_2; opcode stf r_ea_2; # All branch instructions are relative the start of the # branch instruction (the current program counter) plus one. expansion ifa ".ifa (%1 - . - 1), %3, %4\n"; expansion else ".else\n"; expansion endif ".endif\n"; format branch target src code ; # Always opcode bu : jump branch; # Equality opcode beq : cjump branch reads( CC[CC_Z] ); opcode bne : cjump branch reads( CC[CC_Z] ); # Unsigned compare. opcode blo : cjump branch reads( CC[CC_C] ); opcode bls : cjump branch reads( CC[CC_C], CC[CC_Z] ); opcode bhi : cjump branch reads( CC[CC_C], CC[CC_Z] ); opcode bhs : cjump branch reads( CC[CC_C] ); # Signed compare. opcode blt : cjump branch reads( CC[CC_N] ); opcode ble : cjump branch reads( CC[CC_N], CC[CC_Z] ); opcode bgt : cjump branch reads( CC[CC_N], CC[CC_Z] ); opcode bge : cjump branch reads( CC[CC_N] ); # Condition flags. opcode bc : cjump branch reads( CC[CC_C] ); opcode bnc : cjump branch reads( CC[CC_C] ); opcode bz : cjump branch reads( CC[CC_Z] ); opcode bnz : cjump branch reads( CC[CC_Z] ); opcode bv : cjump branch reads( CC[CC_V] ); opcode bnv : cjump branch reads( CC[CC_V] ); opcode buf : cjump branch reads( CC[CC_UF] ); opcode bnuf : cjump branch reads( CC[CC_UF] ); opcode blv : cjump branch reads( CC[CC_LV] ); opcode bnlv : cjump branch reads( CC[CC_LV] ); opcode bluf : cjump branch reads( CC[CC_LUF] ); opcode bnluf : cjump branch reads( CC[CC_LUF] ); opcode bzuf : cjump branch reads( CC[CC_Z], CC[CC_UF] ); format jump target src code ; # Always opcode br : jump expansion "\t%if{%1;%2;\n\tbr %3;%2 %3}%5\n" jump : bu -32768 32767; # Equality opcode jeq : cjump expansion "\t%if{%1;%2;bne 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_Z] ) : beq -32768 32767; opcode jne : cjump expansion "\t%if{%1;%2;beq 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_Z] ) : bne -32768 32767; # Unsigned compare. opcode jlo : cjump expansion "\t%if{%1;%2;bhs 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C] ) : blo -32768 32767; opcode jls : cjump expansion "\t%if{%1;%2;bhi 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C], CC[CC_Z] ) : bls -32768 32767; opcode jhi : cjump expansion "\t%if{%1;%2;bls 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C], CC[CC_Z] ) : bhi -32768 32767; opcode jhs : cjump expansion "\t%if{%1;%2;blo 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C] ) : bhs -32768 32767; # Signed compare. opcode jlt : cjump expansion "\t%if{%1;%2;bge 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_N] ) : blt -32768 32767; opcode jle : cjump expansion "\t%if{%1;%2;bgt 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_N], CC[CC_Z] ) : ble -32768 32767; opcode jgt : cjump expansion "\t%if{%1;%2;ble 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_N], CC[CC_Z] ) : bgt -32768 32767; opcode jge : cjump expansion "\t%if{%1;%2;blt 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_N] ) : bge -32768 32767; # Condition flags. opcode jc : cjump expansion "\t%if{%1;%2;bnc 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C] ) : bc -32768 32767; opcode jnc : cjump expansion "\t%if{%1;%2;bc 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_C] ) : bnc -32768 32767; opcode jz : cjump expansion "\t%if{%1;%2;bnz 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_Z] ) : bz -32768 32767; opcode jnz : cjump expansion "\t%if{%1;%2;bz 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_Z] ) : bnz -32768 32767; opcode jv : cjump expansion "\t%if{%1;%2;bnv 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_V] ) : bv -32768 32767; opcode jnv : cjump expansion "\t%if{%1;%2;bv 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_V] ) : bnv -32768 32767; opcode juf : cjump expansion "\t%if{%1;%2;bnuf 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_UF] ) : buf -32768 32767; opcode jnuf : cjump expansion "\t%if{%1;%2;buf 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_UF] ) : bnuf -32768 32767; opcode jlv : cjump expansion "\t%if{%1;%2;bnlv 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_LV] ) : blv -32768 32767; opcode jnlv : cjump expansion "\t%if{%1;%2;blv 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_LV] ) : bnlv -32768 32767; opcode jluf : cjump expansion "\t%if{%1;%2;bnluf 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_LUF] ) : bluf -32768 32767; opcode jnluf : cjump expansion "\t%if{%1;%2;bluf 1\n\tbr %3;%2 %3}%5\n" jump reads( CC[CC_LUF] ) : bnluf -32768 32767; format call_ind src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode callu : call branch; opcode call : call jump : callu -32768 32767; opcode call_ind : call expansion "\tcallu %3%5\n" call_ind; opcode call_long : call expansion "\tcall %3%5\n" jump; format dbranch lsrc AR rsrc R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | code ; # Always opcode dbu : jump dbranch; # Equality opcode dbeq : cjump dbranch reads( CC[CC_Z] ); opcode dbne : cjump dbranch reads( CC[CC_Z] ); # Unsigned compare. opcode dblo : cjump dbranch reads( CC[CC_C] ); opcode dbls : cjump dbranch reads( CC[CC_C], CC[CC_Z] ); opcode dbhi : cjump dbranch reads( CC[CC_C], CC[CC_Z] ); opcode dbhs : cjump dbranch reads( CC[CC_C] ); # Signed compare. opcode dblt : cjump dbranch reads( CC[CC_N] ); opcode dble : cjump dbranch reads( CC[CC_N], CC[CC_Z] ); opcode dbgt : cjump dbranch reads( CC[CC_N], CC[CC_Z] ); opcode dbge : cjump dbranch reads( CC[CC_N] ); # Condition flags. opcode dbc : cjump dbranch reads( CC[CC_C] ); opcode dbnc : cjump dbranch reads( CC[CC_C] ); opcode dbz : cjump dbranch reads( CC[CC_Z] ); opcode dbnz : cjump dbranch reads( CC[CC_Z] ); opcode dbv : cjump dbranch reads( CC[CC_V] ); opcode dbnv : cjump dbranch reads( CC[CC_V] ); opcode dbuf : cjump dbranch reads( CC[CC_UF] ); opcode dbnuf : cjump dbranch reads( CC[CC_UF] ); opcode dblv : cjump dbranch reads( CC[CC_LV] ); opcode dbnlv : cjump dbranch reads( CC[CC_LV] ); opcode dbluf : cjump dbranch reads( CC[CC_LUF] ); opcode dbnluf : cjump dbranch reads( CC[CC_LUF] ); opcode dbzuf : cjump dbranch reads( CC[CC_Z], CC[CC_UF] ); format fix_ea_r src R | addr | pos_n | neg_n | ind_ix | ind dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode fix fix_ea_r; format float_ea_r src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind dest R ; opcode float float_ea_r; format iack src addr | pos_n | neg_n | ind_ix | ind ; opcode iack iack; format ldp src ldp_addr dest DP ; opcode ldp ldp; format dst_reg dest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; format srcdst_reg lsrcdest R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode pop dst_reg writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); opcode rol srcdst_reg writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode rolc srcdst_reg writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode ror srcdst_reg writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); opcode rorc srcdst_reg writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V], CC[CC_C] ); format popf dest R ; opcode popf popf writes( CC[CC_UF], CC[CC_N], CC[CC_Z], CC[CC_V] ); format src_reg src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP ; opcode push src_reg; format pushf src R ; opcode pushf pushf; format ea src R | AR | IX | DP | BK | ST | IE | IF | IOF | RC | RS | RE | SP | addr | s16 | pos_n | neg_n | ind_ix | ind ; opcode rptb jump; opcode rpts ea; operand spilladdr amode AR + p8 expansion "%1,%2"; format ldspill src spilladdr dest R ; format stspill lsrc R rsrc spilladdr ; expansion lds "*+%aref{,;1;%1}(%aref{,;2;%1}%cond{%2;%2}),%aref{,;3;%1}"; expansion sts "%aref{,;1;%1},*+%aref{,;2;%1}(%aref{,;3;%1}%cond{%2;%2})"; opcode ldspill expansion "\tldfu\t%lds{%3}\n\tldi\t%lds{%3;+1}%5\n" ldspill; opcode stspill expansion "\tstf\t%sts{%3}\n\tsti\t%sts{%3;+1}%5\n" stspill; ### Code tables code do_nothing { $EVAL $dest, $left; } code enter { $SET frame_size = $left; # Save frame pointer. push $reg(AR[7]); # Set new frame pointer. movei $reg(SP), $reg(AR[7]); } code exit { # Restore the frame pointer pop $reg(AR[7]); } oper ENTER : void enter; oper EXIT : void exit; oper ENTERI : void enter; oper EXITI : void exit; code nodouble { $ERROR "Double support not implemented."; } code push ? type(float) { $SET push_size = push_size + 1; pushf $left; } { $SET push_size = push_size + 1; push $left; } code pop ? type(float) { $SET push_size = push_size - 1; popf $left; } { $SET push_size = push_size - 1; pop $left; } oper PUSH : ptr push; oper PUSH : codeptr push; oper PUSH : schar push; oper PUSH : uchar push; oper PUSH : sshort push; oper PUSH : ushort push; oper PUSH : slong push; oper PUSH : ulong push; oper PUSH : float push; oper PUSH : double nodouble; def_user_oper POP : unary side_effect; oper POP : ptr pop; oper POP : codeptr pop; oper POP : schar pop; oper POP : uchar pop; oper POP : sshort pop; oper POP : ushort pop; oper POP : slong pop; oper POP : ulong pop; oper POP : float pop; oper POP : double nodouble; code save_regs { # make room for local variables if any ? is_abs_const( $right ) && ( frame_size > $right ) { addi $mktree( frame_size - $right ), $reg(SP); } {} ? must_preserve_reg(AR[0]) { push $reg(AR[0]); }{} ? must_preserve_reg(AR[1]) { push $reg(AR[1]); }{} ? must_preserve_reg(AR[2]) { push $reg(AR[2]); }{} ? must_preserve_reg(AR[3]) { push $reg(AR[3]); }{} ? must_preserve_reg(AR[4]) { push $reg(AR[4]); }{} ? must_preserve_reg(AR[5]) { push $reg(AR[5]); }{} ? must_preserve_reg(AR[6]) { push $reg(AR[6]); }{} ? must_preserve_reg(AR[7]) { push $reg(AR[7]); }{} # First push the 32 LSBS (32:0) of the register followed # by the 32 MSBS (39:8) of the register. (See restore_regs.) ? must_preserve_reg(R[0]) { push $reg(R[0]); pushf $reg(R[0]); }{} ? must_preserve_reg(R[1]) { push $reg(R[1]); pushf $reg(R[1]); }{} ? must_preserve_reg(R[2]) { push $reg(R[2]); pushf $reg(R[2]); }{} ? must_preserve_reg(R[3]) { push $reg(R[3]); pushf $reg(R[3]); }{} ? must_preserve_reg(R[4]) { push $reg(R[4]); pushf $reg(R[4]); }{} ? must_preserve_reg(R[5]) { push $reg(R[5]); pushf $reg(R[5]); }{} ? must_preserve_reg(R[6]) { push $reg(R[6]); pushf $reg(R[6]); }{} ? must_preserve_reg(R[7]) { push $reg(R[7]); pushf $reg(R[7]); }{} ifelse( CPU, `C4X', ` ? must_preserve_reg(R[8]) { push $reg(R[8]); pushf $reg(R[8]); }{} ? must_preserve_reg(R[9]) { push $reg(R[9]); pushf $reg(R[9]); }{} ? must_preserve_reg(R[10]) { push $reg(R[10]); pushf $reg(R[10]); }{} ? must_preserve_reg(R[11]) { push $reg(R[11]); pushf $reg(R[11]); }{} ' ) ? must_preserve_reg(IR[0]) { push $reg(IR[0]); }{} ? must_preserve_reg(IR[1]) { push $reg(IR[1]); }{} ? must_preserve_reg(BK) { push $reg(BK); }{} ? must_preserve_reg(DP) { push $reg(DP); }{} ? must_preserve_reg(IE) { push $reg(IE); }{} ? must_preserve_reg(IF) { push $reg(IF); }{} ? must_preserve_reg(IOF) { push $reg(IOF); }{} ? must_preserve_reg(RC) { push $reg(RC); }{} ? must_preserve_reg(RE) { push $reg(RE); }{} ? must_preserve_reg(RS) { push $reg(RS); }{} ? must_preserve_reg(ST) { push $reg(ST); }{} ? must_preserve_reg(SP) { push $reg(SP); }{} } code restore_regs { ? must_preserve_reg(SP) { pop $reg(SP); }{} ? must_preserve_reg(ST) { pop $reg(ST); }{} ? must_preserve_reg(RS) { pop $reg(RS); }{} ? must_preserve_reg(RE) { pop $reg(RE); }{} ? must_preserve_reg(RC) { pop $reg(RC); }{} ? must_preserve_reg(IOF) { pop $reg(IOF); }{} ? must_preserve_reg(IF) { pop $reg(IF); }{} ? must_preserve_reg(IE) { pop $reg(IE); }{} ? must_preserve_reg(DP) { pop $reg(DP); }{} ? must_preserve_reg(BK) { pop $reg(BK); }{} ? must_preserve_reg(IR[1]) { pop $reg(IR[1]); }{} ? must_preserve_reg(IR[0]) { pop $reg(IR[0]); }{} # First pop the 32 MSBs into 39:8 of the register; popf will # set 7:0 to zero; then pop 32 LSBs 31:0 of the register. ifelse( CPU, `C4X', ` ? must_preserve_reg(R[11]) { popf $reg(R[11]); pop $reg(R[11]); }{} ? must_preserve_reg(R[10]) { popf $reg(R[10]); pop $reg(R[10]); }{} ? must_preserve_reg(R[9]) { popf $reg(R[9]); pop $reg(R[9]); }{} ? must_preserve_reg(R[8]) { popf $reg(R[8]); pop $reg(R[8]); }{} ' ) ? must_preserve_reg(R[7]) { popf $reg(R[7]); pop $reg(R[7]); }{} ? must_preserve_reg(R[6]) { popf $reg(R[6]); pop $reg(R[6]); }{} ? must_preserve_reg(R[5]) { popf $reg(R[5]); pop $reg(R[5]); }{} ? must_preserve_reg(R[4]) { popf $reg(R[4]); pop $reg(R[4]); }{} ? must_preserve_reg(R[3]) { popf $reg(R[3]); pop $reg(R[3]); }{} ? must_preserve_reg(R[2]) { popf $reg(R[2]); pop $reg(R[2]); }{} ? must_preserve_reg(R[1]) { popf $reg(R[1]); pop $reg(R[1]); }{} ? must_preserve_reg(R[0]) { popf $reg(R[0]); pop $reg(R[0]); }{} ? must_preserve_reg(AR[7]) { pop $reg(AR[7]); }{} ? must_preserve_reg(AR[6]) { pop $reg(AR[6]); }{} ? must_preserve_reg(AR[5]) { pop $reg(AR[5]); }{} ? must_preserve_reg(AR[4]) { pop $reg(AR[4]); }{} ? must_preserve_reg(AR[3]) { pop $reg(AR[3]); }{} ? must_preserve_reg(AR[2]) { pop $reg(AR[2]); }{} ? must_preserve_reg(AR[1]) { pop $reg(AR[1]); }{} ? must_preserve_reg(AR[0]) { pop $reg(AR[0]); }{} # remove space allocated for local variables, if any ? is_abs_const($right) && (frame_size > $right) { subi $mktree( frame_size - $right ), $reg(SP); } } oper SAVE_REGS : void save_regs; oper RESTORE_REGS : void restore_regs; code noargs(opcode) { opcode; } code jump(opcode) { opcode $left; } code callind ? in_any_reg($left) { call_ind $left; } { $EVAL $temp : ptr ulong, $left; call_ind $temp; } oper JUMP : void jump("br"); # switched call to call_long so we don't get .ifa generated for # calls to external labels (which cannot be resolved by the assembler) # rpg 960307 oper CALLDIR : void jump("call_long"); oper CALLIND : void callind; oper RET : void noargs("retsu"); oper RETI : void noargs("retiu"); code asgn(st,move) ? mem_ref($left) && ! (mem_ref($right) || in_any_reg($right)) { # Evaluate sub-expression NOW, before a possible need to set DP. $EVAL $temp, $right; $ASGN $dest, $left, $temp; } ? mem_ref($left) { st $right, $left; $EVAL $dest, $right; } ? in_any_reg($left) && in_any_reg($right) { ? !in_same_set($left, $right) { move $right, $left; } { ? type(float) { movefm $right, $left; } { moveim $right, $left; } } $EVAL $dest,$right; } ? in_any_reg( $left ) { $EVAL $left, $right; $EVAL $dest, $left; } { $ERROR "Unexpected case in code asgn"; } # ASGN with type DOUBLE is a move or spill of a 40-bit register # and $right must be a R register code asgn_d ? in_any_reg( $right ) && in_any_reg( $left ) { # this is a register-to-register move ? in_reg_set( $right, "R" ) && in_reg_set( $left, "R" ) { ? ! in_same_reg( $right, $left ) { # ldf moves all 40 bits of a GPR, except when the # exponent in the GPR is 0x80, in which case it # sets the destination to 0x80 00000000, so we use ldfu movef $right, $left; } } ? !in_reg_set( $right, "R" ) { $ERROR "move (double) not from an R register"; } { $ERROR "move (double) not to an R register" } } ? in_any_reg( $right ) { # this is register spill code ? in_reg_set( $right, "R" ) { # this is a 40-bit register spill; we use stf and sti stspill $right, $left; } { $ERROR "spill (double) not from an R register" } } { $ERROR "spill/move not from a register." } oper ASGN : ptr asgn("sti","movei"); oper ASGN : codeptr asgn("sti","movei"); oper ASGN : schar asgn("sti","movei"); oper ASGN : uchar asgn("sti","movei"); oper ASGN : sshort asgn("sti","movei"); oper ASGN : ushort asgn("sti","movei"); oper ASGN : slong asgn("sti","movei"); oper ASGN : ulong asgn("sti","movei"); oper ASGN : float asgn("stf","movef"); oper ASGN : double asgn_d; code load(ld, move) ? in_any_reg($dest) && in_any_reg($src) { ? !in_same_set($src, $dest) { move $src, $dest; } { ? type(float) { movefm $src, $dest; } { moveim $src, $dest; } } } ? matches($src, s16) { ldi $src, $dest; } ? matches($src, f16) { ldf $src, $dest; } ? ! type(float) && is_abs_const($src) { ifelse( CPU, `C3X', ` # C3X needs this slow code to load a large immediate value # into a register ldi $src.msb, $dest; lsh 16, $dest; or $src.lsb, $dest; ', ` # C4X can do this a bit faster than C3X ldhi $src.msb, $dest; or $src.lsb, $dest; ' ) } ? matches($src, addr) { ld $src, $dest; } ? is_float_const($src) { ldf $src, $dest; } ? mem_ref($src) { ld $src, $dest; } { # Load sub-expression into register. $EVAL $temp, $src; $LOAD $dest, $temp; } # LOAD with type DOUBLE is an unspill of a 40-bit register # and $dest must be a R register code load_d ? in_any_reg( $dest ) { ? in_reg_set( $dest, "R" ) { # unspilling into a 40-bit register; # we load the float part first, since the # integer part will not clobber the exponent ldspill $left, $dest; } { $ERROR "load (double) not to an R register" } } { $ERROR "load (double) not to a register" } oper LOAD : ptr load("ldi", "movei"); oper LOAD : codeptr load("ldi", "movei"); oper LOAD : schar load("ldi", "movei"); oper LOAD : uchar load("ldi", "movei"); oper LOAD : sshort load("ldi", "movei"); oper LOAD : ushort load("ldi", "movei"); oper LOAD : slong load("ldi", "movei"); oper LOAD : ulong load("ldi", "movei"); oper LOAD : float load("ldf", "movef"); oper LOAD : double load_d; code alu_equ(operation, opcode) ? ! in_any_reg($left) { $EVAL $temp, $left; "$"|operation $dest, $temp, $right; $ASGN $nodest, $left, $temp; } { opcode $right, $left; $EVAL $dest, $left; } oper ADDEQ : ptr alu_equ("ADDEQ", "addi"); oper ADDEQ : codeptr alu_equ("ADDEQ", "addi"); oper ADDEQ : schar alu_equ("ADDEQ", "addi"); oper ADDEQ : uchar alu_equ("ADDEQ", "addi"); oper ADDEQ : sshort alu_equ("ADDEQ", "addi"); oper ADDEQ : ushort alu_equ("ADDEQ", "addi"); oper ADDEQ : slong alu_equ("ADDEQ", "addi"); oper ADDEQ : ulong alu_equ("ADDEQ", "addi"); oper ADDEQ : float alu_equ("ADDEQ", "addf"); oper ADDEQ : double nodouble; oper SUBEQ : ptr alu_equ("SUBEQ", "subi"); oper SUBEQ : codeptr alu_equ("SUBEQ", "subi"); oper SUBEQ : schar alu_equ("SUBEQ", "subi"); oper SUBEQ : uchar alu_equ("SUBEQ", "subi"); oper SUBEQ : sshort alu_equ("SUBEQ", "subi"); oper SUBEQ : ushort alu_equ("SUBEQ", "subi"); oper SUBEQ : slong alu_equ("SUBEQ", "subi"); oper SUBEQ : ulong alu_equ("SUBEQ", "subi"); oper SUBEQ : float alu_equ("SUBEQ", "subf"); oper SUBEQ : double nodouble; oper ANDEQ : ptr alu_equ("ANDEQ", "and"); oper ANDEQ : codeptr alu_equ("ANDEQ", "and"); oper ANDEQ : schar alu_equ("ANDEQ", "and"); oper ANDEQ : uchar alu_equ("ANDEQ", "and"); oper ANDEQ : sshort alu_equ("ANDEQ", "and"); oper ANDEQ : ushort alu_equ("ANDEQ", "and"); oper ANDEQ : slong alu_equ("ANDEQ", "and"); oper ANDEQ : ulong alu_equ("ANDEQ", "and"); oper EXOREQ : ptr alu_equ("EXOREQ", "xor"); oper EXOREQ : codeptr alu_equ("EXOREQ", "xor"); oper EXOREQ : schar alu_equ("EXOREQ", "xor"); oper EXOREQ : uchar alu_equ("EXOREQ", "xor"); oper EXOREQ : sshort alu_equ("EXOREQ", "xor"); oper EXOREQ : ushort alu_equ("EXOREQ", "xor"); oper EXOREQ : slong alu_equ("EXOREQ", "xor"); oper EXOREQ : ulong alu_equ("EXOREQ", "xor"); oper OREQ : ptr alu_equ("OREQ", "or"); oper OREQ : codeptr alu_equ("OREQ", "or"); oper OREQ : schar alu_equ("OREQ", "or"); oper OREQ : uchar alu_equ("OREQ", "or"); oper OREQ : sshort alu_equ("OREQ", "or"); oper OREQ : ushort alu_equ("OREQ", "or"); oper OREQ : slong alu_equ("OREQ", "or"); oper OREQ : ulong alu_equ("OREQ", "or"); code alu(opcode) ? in_any_reg($left) && in_any_reg($right) { opcode|"_rrr" $right, $left, $dest; } ? in_any_reg($left) && (matches($right, pos_1) || matches($right, neg_1) || matches($right, ind) || matches($right, ind_ix)) { opcode|"_irr" $right, $left, $dest; } ? (matches($left, pos_1) || matches($left, neg_1) || matches($left, ind) || matches($left, ind_ix)) && in_any_reg($right) { opcode|"_rir" $right, $left, $dest; } ? (matches($left, pos_1) || matches($left, neg_1) || matches($left, ind) || matches($left, ind_ix)) && (matches($right, pos_1) || matches($right, neg_1) || matches($right, ind) || matches($right, ind_ix)) { opcode|"_iir" $right, $left, $dest; } { $EVAL $temp, $left; opcode $right, $temp; $EVAL $dest, $temp; } # # the following appeared to be a faster way to accomplish # the same thing, but it doesn't work if $right and $dest # are the same, or if $right contains a call that might # clobber $dest. # # it's safer to do it as above, and trust the register # allocator to optimize those cases where the extra # step is not necessary # # { # $EVAL $dest, $left; # opcode $right, $dest; # } oper ADD : ptr alu("addi"); oper ADD : codeptr alu("addi"); oper ADD : schar alu("addi"); oper ADD : uchar alu("addi"); oper ADD : sshort alu("addi"); oper ADD : ushort alu("addi"); oper ADD : slong alu("addi"); oper ADD : ulong alu("addi"); oper ADD : float alu("addf"); oper ADD : double nodouble; oper SUB : ptr alu("subi"); oper SUB : codeptr alu("subi"); oper SUB : schar alu("subi"); oper SUB : uchar alu("subi"); oper SUB : sshort alu("subi"); oper SUB : ushort alu("subi"); oper SUB : slong alu("subi"); oper SUB : ulong alu("subi"); oper SUB : float alu("subf"); oper SUB : double nodouble; oper AND : ptr alu("and"); oper AND : codeptr alu("and"); oper AND : schar alu("and"); oper AND : uchar alu("and"); oper AND : sshort alu("and"); oper AND : ushort alu("and"); oper AND : slong alu("and"); oper AND : ulong alu("and"); oper EXOR : ptr alu("xor"); oper EXOR : codeptr alu("xor"); oper EXOR : schar alu("xor"); oper EXOR : uchar alu("xor"); oper EXOR : sshort alu("xor"); oper EXOR : ushort alu("xor"); oper EXOR : slong alu("xor"); oper EXOR : ulong alu("xor"); oper OR : ptr alu("or"); oper OR : codeptr alu("or"); oper OR : schar alu("or"); oper OR : uchar alu("or"); oper OR : sshort alu("or"); oper OR : ushort alu("or"); oper OR : slong alu("or"); oper OR : ulong alu("or"); # multiplication : mult_call # args: r[0-1] # result: r[0] # integer: clobbers: r[1] # float: this is not called for floats opcode mult_call : call expansion "\tcall %3%5\n" jump reads( R[0], R[1] ) writes( R[0], R[1] ) SCRATCHES ; # division : div_call # args: r[0-1] # quotient: r[0] # integer : remainder: r[1] # float : clobbers: r[1] opcode div_call : call expansion "\tcall %3%5\n" jump reads( R[0], R[1] ) writes( R[0], R[1] ) SCRATCHES ; code mult(sign) ifelse( CPU, `C3X', ` # # C3X Version # The mpyi instruction does 24 * 24 bit unsigned multiply, # so we have to call a routine for 32 * 32 bit multiply. { $EXTERN lib = "_mul"|sign; $EVAL $tmp1, $left $EVAL $tmp2, $right $EVAL $reg(R[0]), $tmp1; $EVAL $reg(R[1]), $tmp2; mult_call lib; ? oper( MULEQ ) { $ASGN $dest, $left, $reg(R[0]); } { $EVAL $dest, $reg(R[0]); } } ', ` # C4X Version # The mpyi instruction does 32 * 32 bit unsigned multiply. ? ! in_any_reg($left) { $EVAL $temp, $left; ? oper( MULT ) { $MULT $dest, $temp, $right; } { ? side_effects( $left ) { $ADDR $temp : ptr ulong, $left; $MULEQ $dest, $mktree( *$temp : ptr ulong ), $right; } ? in_any_reg( $dest ) { $MULEQ $dest, $temp, $right; $ASGN $nodest, $left, $dest; } { $MULEQ $temp, $temp, $right; $ASGN $nodest, $left, $temp; } } } ? type(slong) || type(sshort) || type(schar) { # Compute sign of product. xor_rrr $left, $right, $sign; # Compute 32 LSBs of product. mpyi_rrr $left, $right, $temp; # Shift in the sign bit of the product. lsh 1, $temp; rol $sign; rorc $temp; ? oper( MULEQ ) { $ASGN $dest, $left, $temp; } { $EVAL $dest, $temp; } } { mpyi_rrr $left, $right, $temp; ? oper( MULEQ ) { $ASGN $dest, $left, $temp; } { $EVAL $dest, $temp; } } ' ) oper MULEQ : ptr mult("u") rt_call; oper MULEQ : codeptr mult("u") rt_call; oper MULEQ : schar mult("s") rt_call; oper MULEQ : uchar mult("u") rt_call; oper MULEQ : sshort mult("s") rt_call; oper MULEQ : ushort mult("u") rt_call; oper MULEQ : slong mult("s") rt_call; oper MULEQ : ulong mult("u") rt_call; oper MULEQ : float alu_equ("MULEQ", "mpyf"); oper MULEQ : double nodouble; oper MULT : ptr mult("u") rt_call; oper MULT : codeptr mult("u") rt_call; oper MULT : schar mult("s") rt_call; oper MULT : uchar mult("u") rt_call; oper MULT : sshort mult("s") rt_call; oper MULT : ushort mult("u") rt_call; oper MULT : slong mult("s") rt_call; oper MULT : ulong mult("u") rt_call; oper MULT : float alu("mpyf"); oper MULT : double nodouble; code div_rem(sign) { $EXTERN lib = "_div"|sign; $EVAL $tmp1, $left; $EVAL $tmp2, $right; $EVAL $reg(R[0]), $tmp1; $EVAL $reg(R[1]), $tmp2; div_call lib; ? oper(REMEQ) { $ASGN $dest, $left, $reg(R[1]); } ? oper(REM) { $EVAL $dest, $reg(R[1]); } ? oper(DIVEQ) { $ASGN $dest, $left, $reg(R[0]); } { $EVAL $dest, $reg(R[0]); } } oper DIVEQ : ptr div_rem("u") rt_call; oper DIVEQ : codeptr div_rem("u") rt_call; oper DIVEQ : schar div_rem("s") rt_call; oper DIVEQ : uchar div_rem("u") rt_call; oper DIVEQ : sshort div_rem("s") rt_call; oper DIVEQ : ushort div_rem("u") rt_call; oper DIVEQ : slong div_rem("s") rt_call; oper DIVEQ : ulong div_rem("u") rt_call; oper DIVEQ : float div_rem("f") rt_call; oper DIVEQ : double nodouble; oper DIV : ptr div_rem("u") rt_call; oper DIV : codeptr div_rem("u") rt_call; oper DIV : schar div_rem("s") rt_call; oper DIV : uchar div_rem("u") rt_call; oper DIV : sshort div_rem("s") rt_call; oper DIV : ushort div_rem("u") rt_call; oper DIV : slong div_rem("s") rt_call; oper DIV : ulong div_rem("u") rt_call; oper DIV : float div_rem("f") rt_call; oper DIV : double nodouble; oper REMEQ : ptr div_rem("u") rt_call; oper REMEQ : codeptr div_rem("u") rt_call; oper REMEQ : schar div_rem("s") rt_call; oper REMEQ : uchar div_rem("u") rt_call; oper REMEQ : sshort div_rem("s") rt_call; oper REMEQ : ushort div_rem("u") rt_call; oper REMEQ : slong div_rem("s") rt_call; oper REMEQ : ulong div_rem("u") rt_call; # REMEQ undefined for float operands oper REM : ptr div_rem("u") rt_call; oper REM : codeptr div_rem("u") rt_call; oper REM : schar div_rem("s") rt_call; oper REM : uchar div_rem("u") rt_call; oper REM : sshort div_rem("s") rt_call; oper REM : ushort div_rem("u") rt_call; oper REM : slong div_rem("s") rt_call; oper REM : ulong div_rem("u") rt_call; # REM undefined for float operands code unary(opcode) ? matches($left, s16) || matches($left, f16) { opcode $left, $dest; } ? matches($left, f32) || is_abs_const($left) { $LOAD $temp, $left; opcode $temp, $dest; } { opcode $left, $dest; } oper COMPL : ptr unary("not"); oper COMPL : codeptr unary("not"); oper COMPL : schar unary("not"); oper COMPL : uchar unary("not"); oper COMPL : sshort unary("not"); oper COMPL : ushort unary("not"); oper COMPL : slong unary("not"); oper COMPL : ulong unary("not"); oper UMINUS : ptr unary("negi"); oper UMINUS : codeptr unary("negi"); oper UMINUS : schar unary("negi"); oper UMINUS : uchar unary("negi"); oper UMINUS : sshort unary("negi"); oper UMINUS : ushort unary("negi"); oper UMINUS : slong unary("negi"); oper UMINUS : ulong unary("negi"); oper UMINUS : float unary("negf"); oper UMINUS : double nodouble; code shifts_equ(operation) ? ! in_any_reg($left) { $EVAL $temp, $left; "$"|operation $dest, $temp, $right; ? oper(LSHEQ) || oper(RSHEQ) || oper(ARSEQ) { $ASGN $nodest, $left, $temp; }{} } ? oper(LSHEQ) { lsh $right, $left; $EVAL $dest, $left; } ? oper(RSHEQ) { # Positive count shift left, negative shift right. lsh $mktree(- $right), $left; $EVAL $dest, $left; } ? oper(ARSEQ) { # Positive count shift left, negative shift right. ash $mktree(- $right), $left; $EVAL $dest, $left; } { $ERROR "Unexpected case for shift-eq." } oper LSHEQ : ptr shifts_equ("LSHEQ"); oper LSHEQ : codeptr shifts_equ("LSHEQ"); oper LSHEQ : schar shifts_equ("LSHEQ"); oper LSHEQ : uchar shifts_equ("LSHEQ"); oper LSHEQ : sshort shifts_equ("LSHEQ"); oper LSHEQ : ushort shifts_equ("LSHEQ"); oper LSHEQ : slong shifts_equ("LSHEQ"); oper LSHEQ : ulong shifts_equ("LSHEQ"); oper RSHEQ : ptr shifts_equ("RSHEQ"); oper RSHEQ : codeptr shifts_equ("RSHEQ"); oper RSHEQ : schar shifts_equ("RSHEQ"); oper RSHEQ : uchar shifts_equ("RSHEQ"); oper RSHEQ : sshort shifts_equ("RSHEQ"); oper RSHEQ : ushort shifts_equ("RSHEQ"); oper RSHEQ : slong shifts_equ("RSHEQ"); oper RSHEQ : ulong shifts_equ("RSHEQ"); oper ARSEQ : ptr shifts_equ("ARSEQ"); oper ARSEQ : codeptr shifts_equ("ARSEQ"); oper ARSEQ : schar shifts_equ("ARSEQ"); oper ARSEQ : uchar shifts_equ("ARSEQ"); oper ARSEQ : sshort shifts_equ("ARSEQ"); oper ARSEQ : ushort shifts_equ("ARSEQ"); oper ARSEQ : slong shifts_equ("ARSEQ"); oper ARSEQ : ulong shifts_equ("ARSEQ"); code shifts_neq(operation) ? ! in_any_reg($left) { $EVAL $temp, $left; "$"|operation $dest, $temp, $right; } ? oper(LSHIFT) { $EVAL $dest, $left; lsh $right, $dest; } ? oper(RSHIFT) { # Positive count shift left, negative shift right. $EVAL $dest, $left; lsh $mktree(- $right), $dest; } ? oper(ARSHFT) { # Positive count shift left, negative shift right. $EVAL $dest, $left; ash $mktree(- $right), $dest; } { $ERROR "Unexpected case for shift." } oper LSHIFT : ptr shifts_neq("LSHIFT"); oper LSHIFT : codeptr shifts_neq("LSHIFT"); oper LSHIFT : schar shifts_neq("LSHIFT"); oper LSHIFT : uchar shifts_neq("LSHIFT"); oper LSHIFT : sshort shifts_neq("LSHIFT"); oper LSHIFT : ushort shifts_neq("LSHIFT"); oper LSHIFT : slong shifts_neq("LSHIFT"); oper LSHIFT : ulong shifts_neq("LSHIFT"); oper RSHIFT : ptr shifts_neq("RSHIFT"); oper RSHIFT : codeptr shifts_neq("RSHIFT"); oper RSHIFT : schar shifts_neq("RSHIFT"); oper RSHIFT : uchar shifts_neq("RSHIFT"); oper RSHIFT : sshort shifts_neq("RSHIFT"); oper RSHIFT : ushort shifts_neq("RSHIFT"); oper RSHIFT : slong shifts_neq("RSHIFT"); oper RSHIFT : ulong shifts_neq("RSHIFT"); oper ARSHFT : ptr shifts_neq("ARSHFT"); oper ARSHFT : codeptr shifts_neq("ARSHFT"); oper ARSHFT : schar shifts_neq("ARSHFT"); oper ARSHFT : uchar shifts_neq("ARSHFT"); oper ARSHFT : sshort shifts_neq("ARSHFT"); oper ARSHFT : ushort shifts_neq("ARSHFT"); oper ARSHFT : slong shifts_neq("ARSHFT"); oper ARSHFT : ulong shifts_neq("ARSHFT"); code compari ? ! in_any_reg($left) { $EVAL $temp, $left; $COMPARE $nodest, $temp, $right; } { cmpi $right, $left; } code comparf ? ! in_any_reg($left) { $EVAL : float $temp, $left; $COMPARE : float $nodest, $temp, $right; } { cmpf $right, $left; } oper COMPARE : ptr compari; oper COMPARE : codeptr compari; oper COMPARE : schar compari; oper COMPARE : uchar compari; oper COMPARE : sshort compari; oper COMPARE : ushort compari; oper COMPARE : slong compari; oper COMPARE : ulong compari; oper COMPARE : float comparf; oper COMPARE : double nodouble; # $left == $right oper BREQ : ptr jump("jeq"); oper BREQ : codeptr jump("jeq"); oper BREQ : schar jump("jeq"); oper BREQ : uchar jump("jeq"); oper BREQ : sshort jump("jeq"); oper BREQ : ushort jump("jeq"); oper BREQ : slong jump("jeq"); oper BREQ : ulong jump("jeq"); oper BREQ : float jump("jeq"); oper BREQ : double nodouble; # $left != $right oper BRNE : ptr jump("jne"); oper BRNE : codeptr jump("jne"); oper BRNE : schar jump("jne"); oper BRNE : uchar jump("jne"); oper BRNE : sshort jump("jne"); oper BRNE : ushort jump("jne"); oper BRNE : slong jump("jne"); oper BRNE : ulong jump("jne"); oper BRNE : float jump("jne"); oper BRNE : double nodouble; # $left > $right oper BRGT : ptr jump("jhi"); oper BRGT : codeptr jump("jhi"); oper BRGT : schar jump("jgt"); oper BRGT : uchar jump("jhi"); oper BRGT : sshort jump("jgt"); oper BRGT : ushort jump("jhi"); oper BRGT : slong jump("jgt"); oper BRGT : ulong jump("jhi"); oper BRGT : float jump("jgt"); oper BRGT : double nodouble; # $left < $right oper BRLT : ptr jump("jlo"); oper BRLT : codeptr jump("jlo"); oper BRLT : schar jump("jlt"); oper BRLT : uchar jump("jlo"); oper BRLT : sshort jump("jlt"); oper BRLT : ushort jump("jlo"); oper BRLT : slong jump("jlt"); oper BRLT : ulong jump("jlo"); oper BRLT : float jump("jlt"); oper BRLT : double nodouble; # $left >= $right oper BRGE : ptr jump("jhs"); oper BRGE : codeptr jump("jhs"); oper BRGE : schar jump("jge"); oper BRGE : uchar jump("jhs"); oper BRGE : sshort jump("jge"); oper BRGE : ushort jump("jhs"); oper BRGE : slong jump("jge"); oper BRGE : ulong jump("jhs"); oper BRGE : float jump("jge"); oper BRGE : double nodouble; # $left <= $right oper BRLE : ptr jump("jls"); oper BRLE : codeptr jump("jls"); oper BRLE : schar jump("jle"); oper BRLE : uchar jump("jls"); oper BRLE : sshort jump("jle"); oper BRLE : ushort jump("jls"); oper BRLE : slong jump("jle"); oper BRLE : ulong jump("jls"); oper BRLE : float jump("jle"); oper BRLE : double nodouble; code test(type, test, opp) { $COMPARE $nodest, $left, $right; ldi_cond test, 1, $dest; ldi_cond opp, 0, $dest; } oper EQ : ptr test("i", "eq", "ne"); oper EQ : codeptr test("i", "eq", "ne"); oper EQ : schar test("i", "eq", "ne"); oper EQ : uchar test("i", "eq", "ne"); oper EQ : sshort test("i", "eq", "ne"); oper EQ : ushort test("i", "eq", "ne"); oper EQ : slong test("i", "eq", "ne"); oper EQ : ulong test("i", "eq", "ne"); oper EQ : float test("f", "eq", "ne"); oper EQ : double nodouble; oper NE : ptr test("i", "ne", "eq"); oper NE : codeptr test("i", "ne", "eq"); oper NE : schar test("i", "ne", "eq"); oper NE : uchar test("i", "ne", "eq"); oper NE : sshort test("i", "ne", "eq"); oper NE : ushort test("i", "ne", "eq"); oper NE : slong test("i", "ne", "eq"); oper NE : ulong test("i", "ne", "eq"); oper NE : float test("f", "ne", "eq"); oper NE : double nodouble; oper GT : ptr test("i", "hi", "ls"); oper GT : codeptr test("i", "hi", "ls"); oper GT : schar test("i", "gt", "le"); oper GT : uchar test("i", "hi", "ls"); oper GT : sshort test("i", "gt", "le"); oper GT : ushort test("i", "hi", "ls"); oper GT : slong test("i", "gt", "le"); oper GT : ulong test("i", "hi", "ls"); oper GT : float test("f", "gt", "le"); oper GT : double nodouble; oper LT : ptr test("i", "lo", "hs"); oper LT : codeptr test("i", "lo", "hs"); oper LT : schar test("i", "lt", "ge"); oper LT : uchar test("i", "lo", "hs"); oper LT : sshort test("i", "lt", "ge"); oper LT : ushort test("i", "lo", "hs"); oper LT : slong test("i", "lt", "ge"); oper LT : ulong test("i", "lo", "hs"); oper LT : float test("f", "lt", "ge"); oper LT : double nodouble; oper GE : ptr test("i", "hs", "lo"); oper GE : codeptr test("i", "hs", "lo"); oper GE : schar test("i", "ge", "lt"); oper GE : uchar test("i", "hs", "lo"); oper GE : sshort test("i", "ge", "lt"); oper GE : ushort test("i", "hs", "lo"); oper GE : slong test("i", "ge", "lt"); oper GE : ulong test("i", "hs", "lo"); oper GE : float test("f", "ge", "lt"); oper GE : double nodouble; oper LE : ptr test("i", "ls", "hi"); oper LE : codeptr test("i", "ls", "hi"); oper LE : schar test("i", "le", "gt"); oper LE : uchar test("i", "ls", "hi"); oper LE : sshort test("i", "le", "gt"); oper LE : ushort test("i", "ls", "hi"); oper LE : slong test("i", "le", "gt"); oper LE : ulong test("i", "ls", "hi"); oper LE : float test("f", "le", "gt"); oper LE : double nodouble; code pre_post(base_op) { ? oper(POSTINC) || oper(POSTDEC) { $EVAL $dest, $left; } {} "$"|base_op $nodest, $left, $right; ? oper(PREINC) || oper(PREDEC) { $EVAL $dest, $left; } {} } oper PREINC : ptr pre_post("ADDEQ"); oper PREINC : codeptr pre_post("ADDEQ"); oper PREINC : schar pre_post("ADDEQ"); oper PREINC : uchar pre_post("ADDEQ"); oper PREINC : sshort pre_post("ADDEQ"); oper PREINC : ushort pre_post("ADDEQ"); oper PREINC : slong pre_post("ADDEQ"); oper PREINC : ulong pre_post("ADDEQ"); oper PREINC : float pre_post("ADDEQ"); oper PREINC : double nodouble; oper POSTINC : ptr pre_post("ADDEQ"); oper POSTINC : codeptr pre_post("ADDEQ"); oper POSTINC : schar pre_post("ADDEQ"); oper POSTINC : uchar pre_post("ADDEQ"); oper POSTINC : sshort pre_post("ADDEQ"); oper POSTINC : ushort pre_post("ADDEQ"); oper POSTINC : slong pre_post("ADDEQ"); oper POSTINC : ulong pre_post("ADDEQ"); oper POSTINC : float pre_post("ADDEQ"); oper POSTINC : double nodouble; oper PREDEC : ptr pre_post("SUBEQ"); oper PREDEC : codeptr pre_post("SUBEQ"); oper PREDEC : schar pre_post("SUBEQ"); oper PREDEC : uchar pre_post("SUBEQ"); oper PREDEC : sshort pre_post("SUBEQ"); oper PREDEC : ushort pre_post("SUBEQ"); oper PREDEC : slong pre_post("SUBEQ"); oper PREDEC : ulong pre_post("SUBEQ"); oper PREDEC : float pre_post("SUBEQ"); oper PREDEC : double nodouble; oper POSTDEC : ptr pre_post("SUBEQ"); oper POSTDEC : codeptr pre_post("SUBEQ"); oper POSTDEC : schar pre_post("SUBEQ"); oper POSTDEC : uchar pre_post("SUBEQ"); oper POSTDEC : sshort pre_post("SUBEQ"); oper POSTDEC : ushort pre_post("SUBEQ"); oper POSTDEC : slong pre_post("SUBEQ"); oper POSTDEC : ulong pre_post("SUBEQ"); oper POSTDEC : float pre_post("SUBEQ"); oper POSTDEC : double nodouble; # typecasts from floating point # cast float to unsigned long code cast_float_to_unsigned { $EVAL $t1, $left; fix $t1, $dest; negf $t1, $t2; fix $t2, $t2; negi $t2, $t2; ldi_cond "le", $t2, $dest; } # cast float to signed long: # done with a run-time call # arg: r[0] # result: r[0] #opcode cftl_call : call expansion "\tcall %3%5\n" jump # reads( R[0] ) # writes( R[0] ) # SCRATCHES # ; code cast_float_to_signed { # $EXTERN lib = "_ftosi"; # # $EVAL $reg(R[0]), $left; # cftl_call lib # $EVAL $dest, $reg(R[0]); $EVAL $t1, $left; fix $t1, $t2; negf $t1, $t3; fix $t3, $t3; negi $t3, $t3; ldi_cond "le", $t3, $t2; $EVAL $dest, $t2; } # typecasts to floating point # cast a signed int to float code cast_long_to_float ? matches($left, s16) { float $left, $dest; } ? is_abs_const($left) { $LOAD $temp, $left; float $temp, $dest; } { float $left, $dest; } # cast an unsigned int to float: # done with a run-time call # arg: r[0] # result: r[0] #opcode cutf_call : call expansion "\tcall %3%5\n" jump # reads( R[0] ) # writes( R[0] ) # SCRATCHES # ; code cast_ulong_to_float { $EVAL $t1, $left; $AND:ulong $t2, $t1, $mkconst(0x1); $RSHIFT:ulong $t3, $t1, $mkconst(0x1); float $t3, $t3; addf $t3, $t3; float $t2, $t2; addf $t2, $t3; $EVAL $dest, $t3; # $EXTERN lib = "_uitof"; # # $EVAL $reg(R[0]), $src; # cutf_call lib # $EVAL $dest, $reg(R[0]); } oper CAST_SCHAR : ptr do_nothing; oper CAST_SCHAR : codeptr do_nothing; oper CAST_SCHAR : schar do_nothing; oper CAST_SCHAR : uchar do_nothing; oper CAST_SCHAR : sshort do_nothing; oper CAST_SCHAR : ushort do_nothing; oper CAST_SCHAR : slong do_nothing; oper CAST_SCHAR : ulong do_nothing; oper CAST_SCHAR : float cast_long_to_float; oper CAST_SCHAR : double nodouble; oper CAST_UCHAR : ptr do_nothing; oper CAST_UCHAR : codeptr do_nothing; oper CAST_UCHAR : schar do_nothing; oper CAST_UCHAR : uchar do_nothing; oper CAST_UCHAR : sshort do_nothing; oper CAST_UCHAR : ushort do_nothing; oper CAST_UCHAR : slong do_nothing; oper CAST_UCHAR : ulong do_nothing; oper CAST_UCHAR : float cast_ulong_to_float; oper CAST_UCHAR : double nodouble; oper CAST_SSHORT : ptr do_nothing; oper CAST_SSHORT : codeptr do_nothing; oper CAST_SSHORT : schar do_nothing; oper CAST_SSHORT : uchar do_nothing; oper CAST_SSHORT : sshort do_nothing; oper CAST_SSHORT : ushort do_nothing; oper CAST_SSHORT : slong do_nothing; oper CAST_SSHORT : ulong do_nothing; oper CAST_SSHORT : float cast_long_to_float; oper CAST_SSHORT : double nodouble; oper CAST_USHORT : ptr do_nothing; oper CAST_USHORT : codeptr do_nothing; oper CAST_USHORT : schar do_nothing; oper CAST_USHORT : uchar do_nothing; oper CAST_USHORT : sshort do_nothing; oper CAST_USHORT : ushort do_nothing; oper CAST_USHORT : slong do_nothing; oper CAST_USHORT : ulong do_nothing; oper CAST_USHORT : float cast_ulong_to_float; oper CAST_USHORT : double nodouble; oper CAST_SLONG : ptr do_nothing; oper CAST_SLONG : codeptr do_nothing; oper CAST_SLONG : schar do_nothing; oper CAST_SLONG : uchar do_nothing; oper CAST_SLONG : sshort do_nothing; oper CAST_SLONG : ushort do_nothing; oper CAST_SLONG : slong do_nothing; oper CAST_SLONG : ulong do_nothing; oper CAST_SLONG : float cast_long_to_float; oper CAST_SLONG : double nodouble; oper CAST_ULONG : ptr do_nothing; oper CAST_ULONG : codeptr do_nothing; oper CAST_ULONG : schar do_nothing; oper CAST_ULONG : uchar do_nothing; oper CAST_ULONG : sshort do_nothing; oper CAST_ULONG : ushort do_nothing; oper CAST_ULONG : slong do_nothing; oper CAST_ULONG : ulong do_nothing; oper CAST_ULONG : float cast_ulong_to_float; oper CAST_ULONG : double nodouble; oper CAST_FLOAT : ptr cast_float_to_unsigned; oper CAST_FLOAT : codeptr cast_float_to_unsigned; oper CAST_FLOAT : schar cast_float_to_signed; oper CAST_FLOAT : uchar cast_float_to_unsigned; oper CAST_FLOAT : sshort cast_float_to_signed; oper CAST_FLOAT : ushort cast_float_to_unsigned; oper CAST_FLOAT : slong cast_float_to_signed; oper CAST_FLOAT : ulong cast_float_to_unsigned; oper CAST_FLOAT : float do_nothing; oper CAST_FLOAT : double nodouble; oper CAST_DOUBLE : ptr codeptr uchar ushort ulong nodouble; oper CAST_DOUBLE : schar sshort slong nodouble; oper CAST_DOUBLE : float double nodouble; code blkmov { $LABEL last_in_loop; $ADDR $to : ptr ulong, $left; $ADDR $from : ptr ulong, $right; # Nest loops by saving status and loop registers that may be in use. $PUSH : ulong $nodest, $reg(ST); $PUSH : ulong $nodest, $reg(RC); $PUSH : ulong $nodest, $reg(RE); $PUSH : ulong $nodest, $reg(RS); ldi $mktree( tsize($left) - 1 ), $reg(RC); rptb last_in_loop; ldi $mktree( *$from ), $temp : ulong; addi 1, $from; sti $temp, $mktree( *$to ); last_in_loop: addi 1, $to; $POP : ulong $nodest, $reg(RS); $POP : ulong $nodest, $reg(RE); $POP : ulong $nodest, $reg(RC); $POP : ulong $nodest, $reg(ST); $ADDR $dest, $left; } oper BLKMOV : struct blkmov;