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); |                 hop_add_insel(hop, "stwu %H, -4(sp)", src); | ||||||
|                 break; |                 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: |             case burm_float_ATTR: | ||||||
|                 hop_add_insel(hop, "stfsu %H, -4(sp)", src); |                 hop_add_insel(hop, "stfsu %H, -4(sp)", src); | ||||||
|                 break; |                 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); |                 hop_add_insel(hop, "lwz %H, 0(sp)", dest); | ||||||
|                 break; |                 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: |             case burm_float_ATTR: | ||||||
|                 hop_add_insel(hop, "lfs %H, 0(sp)", dest); |                 hop_add_insel(hop, "lfs %H, 0(sp)", dest); | ||||||
|                 break; |                 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); |                     hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|  |                 case burm_double_ATTR: | ||||||
|  |                     hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest); | ||||||
|  |                     break; | ||||||
|  | 
 | ||||||
|                 default: |                 default: | ||||||
|                     assert(false); |                     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); |                     hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|  |                 case burm_double_ATTR: | ||||||
|  |                     hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src); | ||||||
|  |                     break; | ||||||
|  | 
 | ||||||
|                 default: |                 default: | ||||||
|                     assert(false); |                     assert(false); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -408,38 +408,28 @@ PATTERNS | ||||||
| 
 | 
 | ||||||
| /* Comparisons */ | /* 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" |         emit "cmp %cr, 0, %left, %right" | ||||||
| 		cost 4; | 		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) |         when signed_constant(%right, 16) | ||||||
|         emit "cmpi %cr, 0, %left, $right" |         emit "cmpi %cr, 0, %left, $right" | ||||||
| 		cost 4; | 		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" |         emit "cmpl %cr, 0, %left, %right" | ||||||
| 		cost 4; | 		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) |         when signed_constant(%right, 16) | ||||||
|         emit "cmpli %cr, 0, %left, $right" |         emit "cmpli %cr, 0, %left, $right" | ||||||
| 		cost 4; | 		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) |         when specific_constant(%result, 0) | ||||||
|         emit "cmp %cr, 0, %left, %right" |         with %out == %in | ||||||
|         cost 4; |         emit "! COMPARES(cr, 0)" | ||||||
| 
 |  | ||||||
|     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" |  | ||||||
|         cost 4; |         cost 4; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -580,32 +570,61 @@ PATTERNS | ||||||
| 		emit "fsubs %out, %left, %right" | 		emit "fsubs %out, %left, %right" | ||||||
| 		cost 4; | 		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) |     out:(float)reg = MULF4(left:(float)reg, right:(float)reg) | ||||||
|         emit "fmuls %out, %left, %right" |         emit "fmuls %out, %left, %right" | ||||||
|         cost 4; |         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) |     out:(float)reg = NEGF4(left:(float)reg) | ||||||
|         emit "fneg %out, %left" |         emit "fneg %out, %left" | ||||||
|         cost 4; |         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" |         emit "fcmpu %cr, %left, %right" | ||||||
| 		cost 4; | 		cost 4; | ||||||
| 
 | 
 | ||||||
|     cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4) | 	cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg) | ||||||
|         when specific_constant(%result, 0) |  | ||||||
|         emit "fcmpu %cr, %left, %right" |         emit "fcmpu %cr, %left, %right" | ||||||
|         cost 4; | 		cost 4; | ||||||
| 
 | 
 | ||||||
|     out:(ret)reg = CFI44(val:(fret)reg) |     out:(ret)reg = CFI44(val:(fret)reg) | ||||||
|         with corrupted(volatile) |         with corrupted(volatile) | ||||||
|         emit "bl .cfi4" |         emit "bl .cfi44" | ||||||
|         cost 4; |         cost 4; | ||||||
| 
 | 
 | ||||||
|     out:(fret)reg = CIF44(val:(ret)reg) |     out:(fret)reg = CIF44(val:(ret)reg) | ||||||
|         with corrupted(volatile) |         with corrupted(volatile) | ||||||
|         emit "bl .cif4" |         emit "bl .cif44" | ||||||
|         cost 4; |         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 : */ | /* vim: set sw=4 ts=4 expandtab : */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -223,7 +223,10 @@ char* hop_render(struct hop* hop) | ||||||
|             case INSEL_HREG: |             case INSEL_HREG: | ||||||
|             { |             { | ||||||
|                 struct hreg* hreg = insel->u.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; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -69,6 +69,14 @@ static void search_for_promotable_irs(void) | ||||||
|             case IR_MULF: |             case IR_MULF: | ||||||
|             case IR_DIVF: |             case IR_DIVF: | ||||||
|             case IR_NEGF: |             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) |                 if (ir->left) | ||||||
|                     promote(ir->left); |                     promote(ir->left); | ||||||
|                 if (ir->right) |                 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); |     switch (size) | ||||||
|     struct ir* left = pop(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 |     return | ||||||
|         new_ir2( |         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) | static void simple_convert(int opcode) | ||||||
| { | { | ||||||
|     struct ir* destsize = pop(EM_wordsize); |     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_cui: simple_convert(IR_CUI1); break; | ||||||
|         case op_cfi: simple_convert(IR_CFI1); break; |         case op_cfi: simple_convert(IR_CFI1); break; | ||||||
|         case op_cif: simple_convert(IR_CIF1); break; |         case op_cif: simple_convert(IR_CIF1); break; | ||||||
|  |         case op_cff: simple_convert(IR_CFF1); break; | ||||||
| 
 | 
 | ||||||
|         case op_cmp: |         case op_cmp: | ||||||
|             push( |             push( | ||||||
|                 tristate_compare(EM_pointersize, IR_COMPAREU) |                 tristate_compare(EM_pointersize, IR_COMPAREU1) | ||||||
|             ); |             ); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  | @ -276,6 +293,17 @@ static void insn_simple(int opcode) | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         case op_trp: | ||||||
|  |         { | ||||||
|  |             materialise_stack(); | ||||||
|  |             appendir( | ||||||
|  |                 new_ir1( | ||||||
|  |                     IR_CALL, 0, | ||||||
|  |                     new_labelir(".trp") | ||||||
|  |                 ) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         case op_lni: |         case op_lni: | ||||||
|         { |         { | ||||||
|             /* Increment line number --- ignore. */ |             /* Increment line number --- ignore. */ | ||||||
|  | @ -299,10 +327,7 @@ static void simple_branch2(int opcode, int size, | ||||||
|     appendir( |     appendir( | ||||||
|         new_ir2( |         new_ir2( | ||||||
|             irop, 0, |             irop, 0, | ||||||
|             new_ir2( |             compare(left, right, size, IR_COMPARES1), | ||||||
|                 IR_COMPARES,  size, |  | ||||||
|                 left, right |  | ||||||
|             ), |  | ||||||
|             new_ir2( |             new_ir2( | ||||||
|                 IR_PAIR, 0, |                 IR_PAIR, 0, | ||||||
|                 new_bbir(truebb), |                 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_ngf: simple_alu1(opcode, value, IR_NEGF); break; | ||||||
| 
 | 
 | ||||||
|         case op_cmu: /* fall through */ |         case op_cmu: /* fall through */ | ||||||
|         case op_cms: push(tristate_compare(value, IR_COMPAREU)); break; |         case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break; | ||||||
|         case op_cmi: push(tristate_compare(value, IR_COMPARES)); break; |         case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break; | ||||||
|         case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; |         case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break; | ||||||
| 
 | 
 | ||||||
|         case op_lol: |         case op_lol: | ||||||
|             push( |             push( | ||||||
|  | @ -910,8 +935,8 @@ static void insn_ivalue(int opcode, arith value) | ||||||
| 
 | 
 | ||||||
|         case op_fef: |         case op_fef: | ||||||
|         { |         { | ||||||
|             struct ir* e; |  | ||||||
|             struct ir* f = pop(value); |             struct ir* f = pop(value); | ||||||
|  | 
 | ||||||
|             /* fef is implemented by calling a helper function which then mutates
 |             /* 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. We read the return values off the stack when retracting | ||||||
|              * the stack pointer. */ |              * the stack pointer. */ | ||||||
|  | @ -931,6 +956,26 @@ static void insn_ivalue(int opcode, arith value) | ||||||
|             break; |             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: |         case op_lin: | ||||||
|         { |         { | ||||||
|             /* Set line number --- ignore. */ |             /* Set line number --- ignore. */ | ||||||
|  |  | ||||||
|  | @ -74,10 +74,26 @@ S CIF2 | ||||||
| S CIF4 | S CIF4 | ||||||
| S CIF8 | S CIF8 | ||||||
| 
 | 
 | ||||||
|  | S CFF1 | ||||||
|  | S CFF2 | ||||||
|  | S CFF4 | ||||||
|  | S CFF8 | ||||||
|  | 
 | ||||||
| # Tristate comparisons | # Tristate comparisons | ||||||
| S COMPARES | S COMPARES1 | ||||||
| S COMPAREU | S COMPARES2 | ||||||
| S COMPAREF | S COMPARES4 | ||||||
|  | S COMPARES8 | ||||||
|  | 
 | ||||||
|  | S COMPAREU1 | ||||||
|  | S COMPAREU2 | ||||||
|  | S COMPAREU4 | ||||||
|  | S COMPAREU8 | ||||||
|  | 
 | ||||||
|  | S COMPAREF1 | ||||||
|  | S COMPAREF2 | ||||||
|  | S COMPAREF4 | ||||||
|  | S COMPAREF8 | ||||||
| 
 | 
 | ||||||
| # Boolean comparisons | # Boolean comparisons | ||||||
| S IFEQ | S IFEQ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue