diff --git a/mach/proto/mcg/parse_em.c b/mach/proto/mcg/parse_em.c index 167910ad4..27e3a8dda 100644 --- a/mach/proto/mcg/parse_em.c +++ b/mach/proto/mcg/parse_em.c @@ -243,6 +243,10 @@ static void parse_pseu(void) data_offset(dlabel_to_str(em.em_dlb), em.em_off, ro); break; + case sof_ptyp: + data_offset(strdup(em.em_dnam), em.em_off, ro); + break; + case ilb_ptyp: { const char* label = ilabel_to_str(em.em_ilb); @@ -279,6 +283,18 @@ static void parse_pseu(void) data_bss(EM_bsssize, em.em_cst); break; + case ico_ptyp: + case uco_ptyp: + { + arith val = atol(em.em_string); + data_int(val, em.em_size, false); + break; + } + + case sof_ptyp: + data_offset(strdup(em.em_dnam), em.em_off, false); + break; + default: unknown_type("bss"); } diff --git a/mach/proto/mcg/table b/mach/proto/mcg/table index 9a9493199..6a24d9e6b 100644 --- a/mach/proto/mcg/table +++ b/mach/proto/mcg/table @@ -126,6 +126,18 @@ PATTERNS emit "addi sp, sp, $delta" cost 4; + out:(int)reg = GETFP4 + emit "mr %out, fp" + cost 4; + + out:(int)reg = FPTOARGS4(GETFP4) + emit "addi %out, fp, 8" + cost 4; + + out:(int)reg = FPTOARGS4(in:(int)reg) + emit "addi %out, %in, 8" + cost 4; + /* Memory operations */ @@ -354,6 +366,20 @@ PATTERNS +/* Booleans */ + + out:(int)reg = IFEQ4(in:(cr)cr) + emit "mfcr %out" /* get cr0 */ + emit "rlwinmi %out, %out, 32-2, 2, 31" /* extract just EQ */ + cost 8; + + out:(int)reg = IFEQ4(in:(int)reg) + emit "cntlzw %out, %in" /* returns 0..32 */ + emit "rlwinmi %out, %out, 32-5, 5, 31" /* if 32, return 1, otherwise 0 */ + cost 8; + + + /* Conversions */ out:(int)reg = CIU44(in:(int)reg) @@ -406,6 +432,10 @@ PATTERNS emit "neg %out, %left" cost 4; + out:(int)reg = OR4(left:(int)reg, right:(int)reg) + emit "or %out, %right, %left" + cost 4; + out:(int)reg = EOR4(left:(int)reg, right:(int)reg) emit "xor %out, %right, %left" cost 4; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index c2083b8ab..7f0abd19d 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -204,6 +204,15 @@ static void insn_simple(int opcode) ); break; + case op_teq: + push( + new_ir1( + IR_IFEQ, EM_wordsize, + pop(EM_wordsize) + ) + ); + break; + case op_cai: { struct ir* dest = pop(EM_pointersize); @@ -242,6 +251,35 @@ static void insn_simple(int opcode) break; } + case op_lim: + { + push( + new_ir1( + IR_LOAD, 2, + new_labelir(".ignmask") + ) + ); + break; + } + + case op_sim: + { + appendir( + new_ir2( + IR_STORE, 2, + new_labelir(".ignmask"), + pop(EM_wordsize) + ) + ); + break; + } + + case op_lni: + { + /* Increment line number --- ignore. */ + break; + } + default: fatal("treebuilder: unknown simple instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -561,6 +599,7 @@ static void insn_ivalue(int opcode, arith value) break; case op_cmu: + case op_cms: push( tristate_compare(value, IR_COMPAREU) ); @@ -717,6 +756,92 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_sar: + case op_lar: + case op_aar: + { + const char* helper; + if (value != EM_wordsize) + fatal("sar/lar/aar are only supported when using " + "word-size descriptors"); + + switch (opcode) + { + case op_sar: helper = ".sar4"; break; + case op_lar: helper = ".lar4"; break; + case op_aar: helper = ".aar4"; break; + } + + materialise_stack(); + appendir( + new_ir1( + IR_CALL, 0, + new_labelir(helper) + ) + ); + push( + new_ir0( + IR_GETRET, EM_wordsize + ) + ); + break; + } + + case op_lxl: + { + struct ir* ir; + + /* Walk the static chain. */ + + ir = new_ir0( + IR_GETFP, EM_pointersize + ); + + while (value--) + { + ir = new_ir1( + IR_CHAINFP, EM_pointersize, + ir + ); + } + + push(ir); + break; + } + + case op_lxa: + { + struct ir* ir; + + /* Walk the static chain. */ + + ir = new_ir0( + IR_GETFP, EM_pointersize + ); + + while (value--) + { + ir = new_ir1( + IR_CHAINFP, EM_pointersize, + ir + ); + } + + push( + new_ir1( + IR_FPTOARGS, EM_pointersize, + ir + ) + ); + break; + } + + case op_lin: + { + /* Set line number --- ignore. */ + break; + } + default: fatal("treebuilder: unknown ivalue instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -783,6 +908,12 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ) ); break; + + case op_fil: + { + /* Set filename --- ignore. */ + break; + } default: fatal("treebuilder: unknown lvalue instruction '%s'", diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 0667ee04d..44e28e9f8 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -86,4 +86,7 @@ V RET S STACKADJUST S GETRET S SETRET +S GETFP +S CHAINFP +S FPTOARGS