Better (and more correct) floating point conversions; fif; various new opcodes.
This commit is contained in:
		
							parent
							
								
									d535be87b1
								
							
						
					
					
						commit
						f851ab83af
					
				
					 6 changed files with 148 additions and 39 deletions
				
			
		|  | @ -112,6 +112,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* | |||
|                 hop_add_insel(hop, "stwu %H, -4(sp)", src); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_pair_ATTR: | ||||
|                 hop_add_insel(hop, "stwu %0H, -4(sp)", src); | ||||
|                 hop_add_insel(hop, "stwu %1H, -4(sp)", src); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_float_ATTR: | ||||
|                 hop_add_insel(hop, "stfsu %H, -4(sp)", src); | ||||
|                 break; | ||||
|  | @ -130,6 +135,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* | |||
|                 hop_add_insel(hop, "lwz %H, 0(sp)", dest); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_pair_ATTR: | ||||
|                 hop_add_insel(hop, "lwz %0H, 4(sp)", dest); | ||||
|                 hop_add_insel(hop, "lwz %1H, 0(sp)", dest); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_float_ATTR: | ||||
|                 hop_add_insel(hop, "lfs %H, 0(sp)", dest); | ||||
|                 break; | ||||
|  | @ -174,6 +184,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* | |||
|                     hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     assert(false); | ||||
|             } | ||||
|  | @ -190,6 +204,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* | |||
|                     hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     assert(false); | ||||
|             } | ||||
|  |  | |||
|  | @ -408,38 +408,28 @@ PATTERNS | |||
| 
 | ||||
| /* Comparisons */ | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPARES4(left:(int)reg, right:(int)reg) | ||||
| 	cr:(cr)cr = COMPARES44(left:(int)reg, right:(int)reg) | ||||
|         emit "cmp %cr, 0, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPARES4(left:(int)reg, right:CONST4) | ||||
| 	cr:(cr)cr = COMPARES44(left:(int)reg, right:CONST4) | ||||
|         when signed_constant(%right, 16) | ||||
|         emit "cmpi %cr, 0, %left, $right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPAREU4(left:(int)reg, right:(int)reg) | ||||
| 	cr:(cr)cr = COMPAREU44(left:(int)reg, right:(int)reg) | ||||
|         emit "cmpl %cr, 0, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPAREU4(left:(int)reg, right:CONST4) | ||||
| 	cr:(cr)cr = COMPAREU44(left:(int)reg, right:CONST4) | ||||
|         when signed_constant(%right, 16) | ||||
|         emit "cmpli %cr, 0, %left, $right" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:(int)reg), result:CONST4) | ||||
|     out:(cr)cr = COMPARES44(in:(cr)cr, result:CONST4) | ||||
|         when specific_constant(%result, 0) | ||||
|         emit "cmp %cr, 0, %left, %right" | ||||
|         cost 4; | ||||
| 
 | ||||
|     cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:CONST4), result:CONST4) | ||||
|         when specific_constant(%result, 0) | ||||
|         when signed_constant(%right, 16) | ||||
|         emit "cmpi %cr, 0, %left, $right" | ||||
|         cost 4; | ||||
| 
 | ||||
|     cr:(cr)cr = COMPARES4(COMPAREU4(left:(int)reg, right:(int)reg), result:CONST4) | ||||
|         when specific_constant(%result, 0) | ||||
|         emit "cmpl %cr, 0, %left, %right" | ||||
|         with %out == %in | ||||
|         emit "! COMPARES(cr, 0)" | ||||
|         cost 4; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -580,32 +570,61 @@ PATTERNS | |||
| 		emit "fsubs %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = SUBF8(left:(double)reg, right:(double)reg) | ||||
| 		emit "fsub %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     out:(float)reg = MULF4(left:(float)reg, right:(float)reg) | ||||
|         emit "fmuls %out, %left, %right" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(double)reg = MULF8(left:(double)reg, right:(double)reg) | ||||
|         emit "fmul %out, %left, %right" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(float)reg = NEGF4(left:(float)reg) | ||||
|         emit "fneg %out, %left" | ||||
|         cost 4; | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPAREF4(left:(float)reg, right:(float)reg) | ||||
|     out:(double)reg = NEGF8(left:(double)reg) | ||||
|         emit "fneg %out, %left" | ||||
|         cost 4; | ||||
| 
 | ||||
| 	cr:(cr)cr = COMPAREF44(left:(float)reg, right:(float)reg) | ||||
|         emit "fcmpu %cr, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4) | ||||
|         when specific_constant(%result, 0) | ||||
| 	cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg) | ||||
|         emit "fcmpu %cr, %left, %right" | ||||
|         cost 4; | ||||
| 		cost 4; | ||||
| 
 | ||||
|     out:(ret)reg = CFI44(val:(fret)reg) | ||||
|         with corrupted(volatile) | ||||
|         emit "bl .cfi4" | ||||
|         emit "bl .cfi44" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(fret)reg = CIF44(val:(ret)reg) | ||||
|         with corrupted(volatile) | ||||
|         emit "bl .cif4" | ||||
|         emit "bl .cif44" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(ret)reg = CFI84(val:(dret)reg) | ||||
|         with corrupted(volatile) | ||||
|         emit "bl .cfi84" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(dret)reg = CIF48(val:(ret)reg) | ||||
|         with corrupted(volatile) | ||||
|         emit "bl .cif48" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(float)reg = CFF84(val:(double)reg) | ||||
|         emit "frsp %out, %val" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(double)reg = CFF48(val:(float)reg) | ||||
|         emit "fmr %out, %val" | ||||
|         cost 1; | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -223,7 +223,10 @@ char* hop_render(struct hop* hop) | |||
|             case INSEL_HREG: | ||||
|             { | ||||
|                 struct hreg* hreg = insel->u.hreg; | ||||
|                 appendf("%s", hreg->brd->names[insel->index]); | ||||
|                 if (hreg->brd) | ||||
|                     appendf("%s", hreg->brd->names[insel->index]); | ||||
|                 else | ||||
|                     appendf("%s.%d", hreg->id, insel->index); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|  |  | |||
|  | @ -69,6 +69,14 @@ static void search_for_promotable_irs(void) | |||
|             case IR_MULF: | ||||
|             case IR_DIVF: | ||||
|             case IR_NEGF: | ||||
|             case IR_COMPAREF1: | ||||
|             case IR_COMPAREF2: | ||||
|             case IR_COMPAREF4: | ||||
|             case IR_COMPAREF8: | ||||
|             case IR_CFF1: | ||||
|             case IR_CFF2: | ||||
|             case IR_CFF4: | ||||
|             case IR_CFF8: | ||||
|                 if (ir->left) | ||||
|                     promote(ir->left); | ||||
|                 if (ir->right) | ||||
|  |  | |||
|  | @ -149,10 +149,18 @@ static struct ir* convert(struct ir* src, int destsize, int opcode) | |||
|         ); | ||||
| } | ||||
| 
 | ||||
| static struct ir* tristate_compare(int size, int opcode) | ||||
| static struct ir* compare(struct ir* left, struct ir* right, | ||||
|         int size, int opcode) | ||||
| { | ||||
|     struct ir* right = pop(size); | ||||
|     struct ir* left = pop(size); | ||||
|     switch (size) | ||||
|     { | ||||
|         case 1: opcode += 0; break; | ||||
|         case 2: opcode += 1; break; | ||||
|         case 4: opcode += 2; break; | ||||
|         case 8: opcode += 3; break; | ||||
|         default: | ||||
|             fatal("can't compare things of size %d", size); | ||||
|     } | ||||
| 
 | ||||
|     return | ||||
|         new_ir2( | ||||
|  | @ -161,6 +169,14 @@ static struct ir* tristate_compare(int size, int opcode) | |||
|         ); | ||||
| } | ||||
| 
 | ||||
| static struct ir* tristate_compare(int size, int opcode) | ||||
| { | ||||
|     struct ir* right = pop(size); | ||||
|     struct ir* left = pop(size); | ||||
| 
 | ||||
|     return compare(left, right, size, opcode); | ||||
| } | ||||
| 
 | ||||
| static void simple_convert(int opcode) | ||||
| { | ||||
|     struct ir* destsize = pop(EM_wordsize); | ||||
|  | @ -199,10 +215,11 @@ static void insn_simple(int opcode) | |||
|         case op_cui: simple_convert(IR_CUI1); break; | ||||
|         case op_cfi: simple_convert(IR_CFI1); break; | ||||
|         case op_cif: simple_convert(IR_CIF1); break; | ||||
|         case op_cff: simple_convert(IR_CFF1); break; | ||||
| 
 | ||||
|         case op_cmp: | ||||
|             push( | ||||
|                 tristate_compare(EM_pointersize, IR_COMPAREU) | ||||
|                 tristate_compare(EM_pointersize, IR_COMPAREU1) | ||||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|  | @ -276,6 +293,17 @@ static void insn_simple(int opcode) | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case op_trp: | ||||
|         { | ||||
|             materialise_stack(); | ||||
|             appendir( | ||||
|                 new_ir1( | ||||
|                     IR_CALL, 0, | ||||
|                     new_labelir(".trp") | ||||
|                 ) | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         case op_lni: | ||||
|         { | ||||
|             /* Increment line number --- ignore. */ | ||||
|  | @ -299,10 +327,7 @@ static void simple_branch2(int opcode, int size, | |||
|     appendir( | ||||
|         new_ir2( | ||||
|             irop, 0, | ||||
|             new_ir2( | ||||
|                 IR_COMPARES,  size, | ||||
|                 left, right | ||||
|             ), | ||||
|             compare(left, right, size, IR_COMPARES1), | ||||
|             new_ir2( | ||||
|                 IR_PAIR, 0, | ||||
|                 new_bbir(truebb), | ||||
|  | @ -463,9 +488,9 @@ static void insn_ivalue(int opcode, arith value) | |||
|         case op_ngf: simple_alu1(opcode, value, IR_NEGF); break; | ||||
| 
 | ||||
|         case op_cmu: /* fall through */ | ||||
|         case op_cms: push(tristate_compare(value, IR_COMPAREU)); break; | ||||
|         case op_cmi: push(tristate_compare(value, IR_COMPARES)); break; | ||||
|         case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; | ||||
|         case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break; | ||||
|         case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break; | ||||
|         case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break; | ||||
| 
 | ||||
|         case op_lol: | ||||
|             push( | ||||
|  | @ -910,8 +935,8 @@ static void insn_ivalue(int opcode, arith value) | |||
| 
 | ||||
|         case op_fef: | ||||
|         { | ||||
|             struct ir* e; | ||||
|             struct ir* f = pop(value); | ||||
| 
 | ||||
|             /* fef is implemented by calling a helper function which then mutates
 | ||||
|              * the stack. We read the return values off the stack when retracting | ||||
|              * the stack pointer. */ | ||||
|  | @ -931,6 +956,26 @@ static void insn_ivalue(int opcode, arith value) | |||
|             break; | ||||
|         } | ||||
|              | ||||
|         case op_fif: | ||||
|         { | ||||
|             /* fif is implemented by calling a helper function which then mutates
 | ||||
|              * the stack. We read the return values off the stack when retracting | ||||
|              * the stack pointer. */ | ||||
| 
 | ||||
|             /* We start with two floats on the stack. */ | ||||
| 
 | ||||
|             materialise_stack(); | ||||
|             appendir( | ||||
|                 new_ir1( | ||||
|                     IR_CALL, 0, | ||||
|                     new_labelir((value == 4) ? ".fif4" : ".fif8") | ||||
|                 ) | ||||
|             ); | ||||
|                      | ||||
|             /* exit, leaving two floats (or doubles) on the stack. */ | ||||
|             break; | ||||
|         } | ||||
|              | ||||
|         case op_lin: | ||||
|         { | ||||
|             /* Set line number --- ignore. */ | ||||
|  |  | |||
|  | @ -74,10 +74,26 @@ S CIF2 | |||
| S CIF4 | ||||
| S CIF8 | ||||
| 
 | ||||
| S CFF1 | ||||
| S CFF2 | ||||
| S CFF4 | ||||
| S CFF8 | ||||
| 
 | ||||
| # Tristate comparisons | ||||
| S COMPARES | ||||
| S COMPAREU | ||||
| S COMPAREF | ||||
| S COMPARES1 | ||||
| S COMPARES2 | ||||
| S COMPARES4 | ||||
| S COMPARES8 | ||||
| 
 | ||||
| S COMPAREU1 | ||||
| S COMPAREU2 | ||||
| S COMPAREU4 | ||||
| S COMPAREU8 | ||||
| 
 | ||||
| S COMPAREF1 | ||||
| S COMPAREF2 | ||||
| S COMPAREF4 | ||||
| S COMPAREF8 | ||||
| 
 | ||||
| # Boolean comparisons | ||||
| S IFEQ | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue