Add (pretty crummy) support for register aliases and static pairs of registers.
We should have enough functionality now for rather buggy 8-bit ints and doubles. Rework the table and the platform.c to match.
This commit is contained in:
		
							parent
							
								
									d6984d60ac
								
							
						
					
					
						commit
						4db402f229
					
				
					 16 changed files with 422 additions and 161 deletions
				
			
		|  | @ -98,51 +98,122 @@ struct hop* platform_epilogue(void) | |||
| struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest) | ||||
| { | ||||
|     struct hop* hop = new_hop(bb, NULL); | ||||
|     const uint32_t type_attrs = | ||||
|         burm_int_ATTR | burm_pair_ATTR | burm_float_ATTR | burm_double_ATTR; | ||||
| 
 | ||||
|     if (!src->is_stacked && dest->is_stacked) | ||||
|     if ((src->type & type_attrs) != (dest->type & type_attrs)) | ||||
|     { | ||||
|         if (src->type & burm_int_ATTR) | ||||
| 			hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest); | ||||
|         else if (src->type & burm_float_ATTR) | ||||
|             hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); | ||||
|         else | ||||
|             assert(false); | ||||
|     } | ||||
|     else if (src->is_stacked && !dest->is_stacked) | ||||
|     { | ||||
|         if (src->type & burm_int_ATTR) | ||||
| 			hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src); | ||||
|         else if (src->type & burm_float_ATTR) | ||||
|             hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); | ||||
|         else | ||||
|             assert(false); | ||||
|     } | ||||
|     else if (!src->is_stacked && !dest->is_stacked) | ||||
|     { | ||||
|         if ((src->type & burm_int_ATTR) && (dest->type & burm_int_ATTR)) | ||||
| 			hop_add_insel(hop, "mr %H, %H", dest, src); | ||||
|         else if ((src->type & burm_float_ATTR) && (dest->type & burm_float_ATTR)) | ||||
|             hop_add_insel(hop, "fmr %H, %H", dest, src); | ||||
|         else | ||||
|         assert(!src->is_stacked); | ||||
|         assert(!dest->is_stacked); | ||||
| 
 | ||||
|         switch (src->type & type_attrs) | ||||
|         { | ||||
|             if (src->type & burm_int_ATTR) | ||||
|             case burm_int_ATTR: | ||||
|                 hop_add_insel(hop, "stwu %H, -4(sp)", src); | ||||
|             else if (src->type & burm_float_ATTR) | ||||
|                 hop_add_insel(hop, "stfsu %H, -4(sp)", src); | ||||
|             else | ||||
|                 assert(false); | ||||
|                 break; | ||||
| 
 | ||||
|             if (dest->type & burm_int_ATTR) | ||||
|                 hop_add_insel(hop, "lwz %H, 0(sp)", dest); | ||||
|             else if (dest->type & burm_float_ATTR) | ||||
|                 hop_add_insel(hop, "lfs %H, 0(sp)", dest); | ||||
|             else | ||||
|             case burm_float_ATTR: | ||||
|                 hop_add_insel(hop, "stfsu %H, -4(sp)", src); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_double_ATTR: | ||||
|                 hop_add_insel(hop, "stfdu %H, -8(sp)", src); | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 assert(false); | ||||
|             hop_add_insel(hop, "addi sp, sp, 4"); | ||||
|         } | ||||
| 	} | ||||
| 	else | ||||
| 		fatal("cannot generate move from %s to %s", src->name, dest->name); | ||||
| 
 | ||||
|         switch (dest->type & type_attrs) | ||||
|         { | ||||
|             case burm_int_ATTR: | ||||
|                 hop_add_insel(hop, "lwz %H, 0(sp)", dest); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_float_ATTR: | ||||
|                 hop_add_insel(hop, "lfs %H, 0(sp)", dest); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_double_ATTR: | ||||
|                 hop_add_insel(hop, "lfd %H, 0(sp)", dest); | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 assert(false); | ||||
|         } | ||||
| 
 | ||||
|         switch (dest->type & type_attrs) | ||||
|         { | ||||
|             case burm_int_ATTR: | ||||
|             case burm_float_ATTR: | ||||
|                 hop_add_insel(hop, "addi sp, sp, 4"); | ||||
|                 break; | ||||
| 
 | ||||
|             case burm_double_ATTR: | ||||
|             case burm_pair_ATTR: | ||||
|                 hop_add_insel(hop, "addi sp, sp, 8"); | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 assert(false); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         uint32_t type = src->type & type_attrs; | ||||
| 
 | ||||
|         if (!src->is_stacked && dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "stw %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                     hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     assert(false); | ||||
|             } | ||||
|         } | ||||
|         else if (src->is_stacked && !dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "lwz %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                     hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     assert(false); | ||||
|             } | ||||
|         } | ||||
|         else if (!src->is_stacked && !dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "mr %H, %H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "fmr %H, %H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     assert(false); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|             assert(false); | ||||
|     } | ||||
| 
 | ||||
|     return hop; | ||||
| } | ||||
|  |  | |||
|  | @ -7,71 +7,122 @@ REGISTERS | |||
|      * a register into another register (e.g. for eviction). | ||||
|      */ | ||||
| 
 | ||||
|     r12 "r12" bytes4! int! volatile;  | ||||
|     r11 "r11" bytes4! int! volatile;  | ||||
|     r10 "r10" bytes4! int! volatile;  | ||||
|     r9  "r9"  bytes4! int! volatile; | ||||
|     r8  "r8"  bytes4! int! volatile; | ||||
|     r7  "r7"  bytes4! int! volatile; | ||||
|     r6  "r6"  bytes4! int! volatile; | ||||
|     r5  "r5"  bytes4! int! volatile; | ||||
|     r4  "r4"  bytes4! int! volatile; | ||||
|     r3  "r3"  bytes4! int! volatile ret; | ||||
|     r12                                           bytes4! int! volatile;  | ||||
|     r11                                           bytes4! int! volatile;  | ||||
|     r10                                           bytes4! int! volatile;  | ||||
|     r9                                            bytes4! int! volatile; | ||||
|     r8                                            bytes4! int! volatile; | ||||
|     r7                                            bytes4! int! volatile; | ||||
|     r6                                            bytes4! int! volatile; | ||||
|     r5                                            bytes4! int! volatile; | ||||
|     r4                                            bytes4! int! volatile; | ||||
|     r3                                            bytes4! int! volatile ret; | ||||
| 
 | ||||
|     r31 "r31" bytes4! int!;  | ||||
|     r30 "r30" bytes4! int!;  | ||||
|     r29 "r29" bytes4! int!;  | ||||
|     r28 "r28" bytes4! int!;  | ||||
|     r27 "r27" bytes4! int!;  | ||||
|     r26 "r26" bytes4! int!;  | ||||
|     r25 "r25" bytes4! int!;  | ||||
|     r24 "r24" bytes4! int!;  | ||||
|     r23 "r23" bytes4! int!;  | ||||
|     r22 "r22" bytes4! int!;  | ||||
|     r21 "r21" bytes4! int!;  | ||||
|     r20 "r20" bytes4! int!;  | ||||
|     r19 "r19" bytes4! int!;  | ||||
|     r18 "r18" bytes4! int!;  | ||||
|     r17 "r17" bytes4! int!;  | ||||
|     r16 "r16" bytes4! int!; | ||||
|     r15 "r15" bytes4! int!; | ||||
|     r14 "r14" bytes4! int!; | ||||
|     r31                                           bytes4! int!;  | ||||
|     r30                                           bytes4! int!;  | ||||
|     r29                                           bytes4! int!;  | ||||
|     r28                                           bytes4! int!;  | ||||
|     r27                                           bytes4! int!;  | ||||
|     r26                                           bytes4! int!;  | ||||
|     r25                                           bytes4! int!;  | ||||
|     r24                                           bytes4! int!;  | ||||
|     r23                                           bytes4! int!;  | ||||
|     r22                                           bytes4! int!;  | ||||
|     r21                                           bytes4! int!;  | ||||
|     r20                                           bytes4! int!;  | ||||
|     r19                                           bytes4! int!;  | ||||
|     r18                                           bytes4! int!;  | ||||
|     r17                                           bytes4! int!;  | ||||
|     r16                                           bytes4! int!; | ||||
|     r15                                           bytes4! int!; | ||||
|     r14                                           bytes4! int!; | ||||
|     r13                                           bytes4! int!; | ||||
| 
 | ||||
|     f14 "f14" bytes4! float! volatile; | ||||
|     f13 "f13" bytes4! float! volatile; | ||||
|     f12 "f12" bytes4! float! volatile; | ||||
|     f11 "f11" bytes4! float! volatile; | ||||
|     f10 "f10" bytes4! float! volatile; | ||||
|     f9  "f9"  bytes4! float! volatile; | ||||
|     f8  "f8"  bytes4! float! volatile; | ||||
|     f7  "f7"  bytes4! float! volatile; | ||||
|     f6  "f6"  bytes4! float! volatile; | ||||
|     f5  "f5"  bytes4! float! volatile; | ||||
|     f4  "f4"  bytes4! float! volatile; | ||||
|     f3  "f3"  bytes4! float! volatile fret; | ||||
|     f2  "f2"  bytes4! float! volatile; | ||||
|     f1  "f1"  bytes4! float! volatile; | ||||
|     f0  "f0"  bytes4! float! volatile; | ||||
|     r11r12  named("r11", "r12") aliases(r11, r12) bytes8! pair! volatile; | ||||
|     r9r10   named("r9",  "r10") aliases(r9,  r10) bytes8! pair! volatile; | ||||
|     r7r8    named("r7",  "r8")  aliases(r7,  r8)  bytes8! pair! volatile; | ||||
|     r5r6    named("r5",  "r6")  aliases(r6,  r6)  bytes8! pair! volatile; | ||||
|     r3r4    named("r3",  "r4")  aliases(r3,  r4)  bytes8! pair! volatile pret; | ||||
| 
 | ||||
|     f31 "f31" bytes4! float!; | ||||
|     f30 "f30" bytes4! float!; | ||||
|     f29 "f29" bytes4! float!; | ||||
|     f28 "f28" bytes4! float!; | ||||
|     f27 "f27" bytes4! float!; | ||||
|     f26 "f26" bytes4! float!; | ||||
|     f25 "f25" bytes4! float!; | ||||
|     f24 "f24" bytes4! float!; | ||||
|     f23 "f23" bytes4! float!; | ||||
|     f22 "f22" bytes4! float!; | ||||
|     f21 "f21" bytes4! float!; | ||||
|     f20 "f20" bytes4! float!; | ||||
|     f19 "f19" bytes4! float!; | ||||
|     f18 "f18" bytes4! float!; | ||||
|     f17 "f17" bytes4! float!; | ||||
|     f16 "f16" bytes4! float!; | ||||
|     f15 "f15" bytes4! float!; | ||||
|              | ||||
| 	cr0 "cr0" cr!; | ||||
|     r29r30  named("r29", "r30") aliases(r29, r30) bytes8! pair!; | ||||
|     r27r28  named("r27", "r28") aliases(r27, r28) bytes8! pair!; | ||||
|     r25r26  named("r25", "r26") aliases(r25, r26) bytes8! pair!; | ||||
|     r23r24  named("r23", "r24") aliases(r23, r24) bytes8! pair!; | ||||
|     r21r22  named("r21", "r22") aliases(r21, r22) bytes8! pair!; | ||||
|     r19r20  named("r19", "r20") aliases(r19, r20) bytes8! pair!; | ||||
|     r17r18  named("r17", "r18") aliases(r17, r18) bytes8! pair!; | ||||
|     r15r16  named("r15", "r16") aliases(r15, r16) bytes8! pair!; | ||||
|     r13r14  named("r13", "r14") aliases(r13, r14) bytes8! pair!; | ||||
| 
 | ||||
|     f14                                           bytes4! float! volatile; | ||||
|     f13                                           bytes4! float! volatile; | ||||
|     f12                                           bytes4! float! volatile; | ||||
|     f11                                           bytes4! float! volatile; | ||||
|     f10                                           bytes4! float! volatile; | ||||
|     f9                                            bytes4! float! volatile; | ||||
|     f8                                            bytes4! float! volatile; | ||||
|     f7                                            bytes4! float! volatile; | ||||
|     f6                                            bytes4! float! volatile; | ||||
|     f5                                            bytes4! float! volatile; | ||||
|     f4                                            bytes4! float! volatile; | ||||
|     f3                                            bytes4! float! volatile fret; | ||||
|     f2                                            bytes4! float! volatile; | ||||
|     f1                                            bytes4! float! volatile; | ||||
|     f0                                            bytes4! float! volatile; | ||||
| 
 | ||||
|     f31                                           bytes4! float!; | ||||
|     f30                                           bytes4! float!; | ||||
|     f29                                           bytes4! float!; | ||||
|     f28                                           bytes4! float!; | ||||
|     f27                                           bytes4! float!; | ||||
|     f26                                           bytes4! float!; | ||||
|     f25                                           bytes4! float!; | ||||
|     f24                                           bytes4! float!; | ||||
|     f23                                           bytes4! float!; | ||||
|     f22                                           bytes4! float!; | ||||
|     f21                                           bytes4! float!; | ||||
|     f20                                           bytes4! float!; | ||||
|     f19                                           bytes4! float!; | ||||
|     f18                                           bytes4! float!; | ||||
|     f17                                           bytes4! float!; | ||||
|     f16                                           bytes4! float!; | ||||
|     f15                                           bytes4! float!; | ||||
| 
 | ||||
|     d14     named("f14")       aliases(f14)       bytes8! double! volatile; | ||||
|     d13     named("f13")       aliases(f13)       bytes8! double! volatile; | ||||
|     d12     named("f12")       aliases(f12)       bytes8! double! volatile; | ||||
|     d11     named("f11")       aliases(f11)       bytes8! double! volatile; | ||||
|     d10     named("f10")       aliases(f10)       bytes8! double! volatile; | ||||
|     d9      named("f9")        aliases(f9)        bytes8! double! volatile; | ||||
|     d8      named("f8")        aliases(f8)        bytes8! double! volatile; | ||||
|     d7      named("f7")        aliases(f7)        bytes8! double! volatile; | ||||
|     d6      named("f6")        aliases(f6)        bytes8! double! volatile; | ||||
|     d5      named("f5")        aliases(f5)        bytes8! double! volatile; | ||||
|     d4      named("f4")        aliases(f4)        bytes8! double! volatile; | ||||
|     d3      named("f3")        aliases(f3)        bytes8! double! volatile dret; | ||||
|     d2      named("f2")        aliases(f2)        bytes8! double! volatile; | ||||
|     d1      named("f1")        aliases(f1)        bytes8! double! volatile; | ||||
|     d0      named("f0")        aliases(f0)        bytes8! double! volatile; | ||||
| 
 | ||||
|     d31     named("f31")       aliases(f31)       bytes8! double!; | ||||
|     d30     named("f30")       aliases(f30)       bytes8! double!; | ||||
|     d29     named("f29")       aliases(f29)       bytes8! double!; | ||||
|     d28     named("f28")       aliases(f28)       bytes8! double!; | ||||
|     d27     named("f27")       aliases(f27)       bytes8! double!; | ||||
|     d26     named("f26")       aliases(f26)       bytes8! double!; | ||||
|     d25     named("f25")       aliases(f25)       bytes8! double!; | ||||
|     d24     named("f24")       aliases(f24)       bytes8! double!; | ||||
|     d23     named("f23")       aliases(f23)       bytes8! double!; | ||||
|     d22     named("f22")       aliases(f22)       bytes8! double!; | ||||
|     d21     named("f21")       aliases(f21)       bytes8! double!; | ||||
|     d20     named("f20")       aliases(f20)       bytes8! double!; | ||||
|     d19     named("f19")       aliases(f19)       bytes8! double!; | ||||
|     d18     named("f18")       aliases(f18)       bytes8! double!; | ||||
|     d17     named("f17")       aliases(f17)       bytes8! double!; | ||||
|     d16     named("f16")       aliases(f16)       bytes8! double!; | ||||
|     d15     named("f15")       aliases(f15)       bytes8! double!; | ||||
| 
 | ||||
| 	cr0                                           cr!; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -101,6 +152,11 @@ PATTERNS | |||
| 		emit "stwu %in, -4(sp)" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     PUSH8(in:(pair)reg) | ||||
|         emit "stwu %in.0, -4(sp)" | ||||
|         emit "stwu %in.1, -4(sp)" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = POP4 | ||||
| 		emit "lwz %out, 0(sp)" | ||||
|         emit "addi sp, sp, 4" | ||||
|  | @ -113,12 +169,20 @@ PATTERNS | |||
| 		 | ||||
| 	SETRET4(in:(ret)reg) | ||||
| 		emit "! setret4" | ||||
| 		cost 4; | ||||
| 		cost 1; | ||||
| 
 | ||||
|     SETRET8(in:(pret)reg) | ||||
|         emit "! setret8" | ||||
|         cost 1; | ||||
| 
 | ||||
|     (ret)reg = GETRET4 | ||||
|         emit "! getret4" | ||||
|         cost 1; | ||||
| 
 | ||||
|     (pret)reg = GETRET8 | ||||
|         emit "! getret8" | ||||
|         cost 1; | ||||
| 
 | ||||
| 	STACKADJUST4(delta:CONST4) | ||||
|         when signed_constant(%delta, 16) | ||||
| 		emit "addi sp, sp, $delta" | ||||
|  | @ -142,6 +206,11 @@ PATTERNS | |||
| 
 | ||||
|     /* Stores */ | ||||
| 
 | ||||
| 	STORE8(addr:address, value:(pair)reg) | ||||
| 		emit "stw %value.0, 4+%addr" | ||||
| 		emit "stw %value.1, 0+%addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	STORE4(addr:address, value:(int)reg) | ||||
| 		emit "stw %value, %addr" | ||||
| 		cost 4; | ||||
|  | @ -168,6 +237,11 @@ PATTERNS | |||
| 		emit "lwz %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     out:(pair)reg = LOAD8(addr:address) | ||||
|         emit "lwz %out.0, 4+%addr" | ||||
|         emit "lwz %out.1, 0+%addr" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	out:(int)ushort0 = LOAD2(addr:address) | ||||
| 		emit "lhz %out, %addr" | ||||
| 		cost 4; | ||||
|  | @ -480,6 +554,10 @@ PATTERNS | |||
|         emit "lfs %out, %addr" | ||||
|         cost 4; | ||||
|          | ||||
|     out:(double)reg = LOADF8(addr:address) | ||||
|         emit "lfd %out, %addr" | ||||
|         cost 4; | ||||
|          | ||||
| 	out:(float)reg = value:CONSTF4 | ||||
| 		emit "lfs %out, address-containing-$value" | ||||
| 		cost 8; | ||||
|  | @ -488,6 +566,10 @@ PATTERNS | |||
| 		emit "fadds %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = ADDF8(left:(double)reg, right:(double)reg) | ||||
| 		emit "fadd %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = SUBF4(left:(float)reg, right:(float)reg) | ||||
| 		emit "fsubs %out, %left, %right" | ||||
| 		cost 4; | ||||
|  |  | |||
|  | @ -31,17 +31,19 @@ void hop_add_string_insel(struct hop* hop, const char* string) | |||
| 	array_append(&hop->insels, insel); | ||||
| } | ||||
| 
 | ||||
| void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg) | ||||
| void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg, int index) | ||||
| { | ||||
| 	struct insel* insel = new_insel(INSEL_HREG); | ||||
| 	insel->u.hreg = hreg; | ||||
|     insel->index = index; | ||||
| 	array_append(&hop->insels, insel); | ||||
| } | ||||
| 
 | ||||
| void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg) | ||||
| void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg, int index) | ||||
| { | ||||
| 	struct insel* insel = new_insel(INSEL_VREG); | ||||
| 	insel->u.vreg = vreg; | ||||
|     insel->index = index; | ||||
| 	array_append(&hop->insels, insel); | ||||
| } | ||||
| 
 | ||||
|  | @ -108,11 +110,11 @@ void hop_add_insel(struct hop* hop, const char* fmt, ...) | |||
|                     break; | ||||
| 
 | ||||
|                 case 'H': | ||||
|                     hop_add_hreg_insel(hop, va_arg(ap, struct hreg*)); | ||||
|                     hop_add_hreg_insel(hop, va_arg(ap, struct hreg*), 0); | ||||
|                     break; | ||||
| 
 | ||||
|                 case 'V': | ||||
|                     hop_add_vreg_insel(hop, va_arg(ap, struct vreg*)); | ||||
|                     hop_add_vreg_insel(hop, va_arg(ap, struct vreg*), 0); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|  | @ -205,7 +207,7 @@ char* hop_render(struct hop* hop) | |||
|             case INSEL_HREG: | ||||
|             { | ||||
|                 struct hreg* hreg = insel->u.hreg; | ||||
|                 appendf("%s", hreg->realname); | ||||
|                 appendf("%s", hreg->brd->names[insel->index]); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|  | @ -216,7 +218,7 @@ char* hop_render(struct hop* hop) | |||
|                 if (!hreg) | ||||
|                     hreg = pmap_findright(&hop->regsout, vreg); | ||||
|                 if (hreg) | ||||
|                     appendf("%s", hreg->realname); | ||||
|                     appendf("%s", hreg->brd->names[insel->index]); | ||||
|                 else | ||||
|                     appendf("%%%d", vreg->id); | ||||
| 				break; | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ enum insel_type | |||
| struct insel | ||||
| { | ||||
| 	enum insel_type type; | ||||
|     int index; | ||||
| 	union | ||||
| 	{ | ||||
| 		const char* string; | ||||
|  | @ -54,8 +55,8 @@ struct hop | |||
| extern struct hop* new_hop(struct basicblock* bb, struct ir* ir); | ||||
| 
 | ||||
| extern void hop_add_string_insel(struct hop* hop, const char* string); | ||||
| extern void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg); | ||||
| extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg); | ||||
| extern void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg, int index); | ||||
| extern void hop_add_vreg_insel(struct hop* hop, struct vreg* vreg, int index); | ||||
| extern void hop_add_value_insel(struct hop* hop, struct ir* ir); | ||||
| extern void hop_add_st_offset_insel(struct hop* hop, struct hreg* hreg); | ||||
| extern void hop_add_ab_offset_insel(struct hop* hop, int offset); | ||||
|  |  | |||
|  | @ -32,9 +32,9 @@ void burm_panic_cannot_match(struct burm_node* node) | |||
| 	exit(1); | ||||
| } | ||||
| 
 | ||||
| static void emit_return_reg(void) | ||||
| static void emit_return_reg(int index) | ||||
| { | ||||
|     hop_add_vreg_insel(current_hop, current_hop->output); | ||||
|     hop_add_vreg_insel(current_hop, current_hop->output, index); | ||||
| } | ||||
| 
 | ||||
| static struct vreg* find_vreg_of_child(int child) | ||||
|  | @ -47,13 +47,13 @@ static struct vreg* find_vreg_of_child(int child) | |||
|         return insn->ir->result; | ||||
| } | ||||
| 
 | ||||
| static void emit_reg(int child) | ||||
| static void emit_reg(int child, int index) | ||||
| { | ||||
|     struct vreg* vreg = find_vreg_of_child(child); | ||||
| 
 | ||||
|     if (vreg) | ||||
|     { | ||||
|         hop_add_vreg_insel(current_hop, vreg); | ||||
|         hop_add_vreg_insel(current_hop, vreg, index); | ||||
|         array_appendu(&vreg->used, current_hop); | ||||
|     } | ||||
| } | ||||
|  | @ -109,7 +109,7 @@ static uint32_t find_type_from_constraint(uint32_t attr) | |||
|      * this. */ | ||||
| 
 | ||||
|     const struct burm_register_data* brd = burm_register_data; | ||||
|     while (brd->name) | ||||
|     while (brd->id) | ||||
|     { | ||||
|         if (brd->attrs & attr) | ||||
|             return brd->type; | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ static void promote(struct ir* ir) | |||
|         { | ||||
|             int i; | ||||
|             for (i=0; i<ir->u.phivalue.count; i++) | ||||
|                 array_appendu(&promotable, ir->u.phivalue.item[i].right); | ||||
|                 promote(ir->u.phivalue.item[i].right); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -20,14 +20,30 @@ static bool type_match(struct hreg* hreg, struct vreg* vreg); | |||
| 
 | ||||
| static void populate_hregs(void) | ||||
| { | ||||
|     int i; | ||||
|     const struct burm_register_data* brd = burm_register_data; | ||||
| 
 | ||||
|     hregs.count = 0; | ||||
|     while (brd->name) | ||||
|     while (brd->id) | ||||
|     { | ||||
|         array_append(&hregs, new_hreg(brd)); | ||||
|         brd++; | ||||
|     } | ||||
|      | ||||
|     /* Wire up the register aliases. */ | ||||
| 
 | ||||
|     for (i=0; i<hregs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = hregs.item[i]; | ||||
|         const struct burm_register_data** alias = hreg->brd->aliases; | ||||
| 
 | ||||
|         while (*alias) | ||||
|         { | ||||
|             int index = *alias - burm_register_data; | ||||
|             array_append(&hreg->aliases, hregs.item[index]); | ||||
|             alias++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void wire_up_blocks_ins_outs(void) | ||||
|  | @ -43,6 +59,20 @@ static void wire_up_blocks_ins_outs(void) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool register_used(register_assignment_t* regs, struct hreg* hreg) | ||||
| { | ||||
|     int i; | ||||
| 
 | ||||
|     for (i=0; i<hreg->aliases.count; i++) | ||||
|     { | ||||
|         struct hreg* alias = hreg->aliases.item[i]; | ||||
|         if (pmap_findleft(regs, alias)) | ||||
|             return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static struct hreg* allocate_phi_hreg(register_assignment_t* regs, | ||||
|     struct vreg* vreg, uint32_t type) | ||||
| { | ||||
|  | @ -54,7 +84,7 @@ static struct hreg* allocate_phi_hreg(register_assignment_t* regs, | |||
|     for (i=0; i<hregs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = hregs.item[i]; | ||||
|         if (!pmap_findleft(regs, hreg) && (hreg->type == type)) | ||||
|         if (!register_used(regs, hreg) && (hreg->type == type)) | ||||
|         { | ||||
|             /* This one is unused. Use it. */ | ||||
|             return hreg; | ||||
|  | @ -86,7 +116,10 @@ static struct hreg* evict(struct vreg* vreg) | |||
| 
 | ||||
|         if (evictable(hreg, vreg)) | ||||
|         { | ||||
|             if (!candidatein && !candidateout) | ||||
|             if (!candidatein && | ||||
|                 !candidateout && | ||||
|                 !register_used(current_ins, hreg) && | ||||
|                 !register_used(current_outs, hreg)) | ||||
|             { | ||||
|                 /* This hreg is unused, so we don't need to evict anything.
 | ||||
|                  * Shouldn't really happen in real life. */ | ||||
|  | @ -95,7 +128,7 @@ static struct hreg* evict(struct vreg* vreg) | |||
|             if (candidatein == candidateout) | ||||
|             { | ||||
|                 /* This is a through register. */ | ||||
|                 tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->name); | ||||
|                 tracef('R', "R: evicting %%%d from %s\n", candidatein->id, hreg->id); | ||||
|                 pmap_put(&evicted, candidatein, hreg); | ||||
|                 pmap_remove(current_ins, hreg, candidatein); | ||||
|                 pmap_remove(current_outs, hreg, candidatein); | ||||
|  | @ -120,13 +153,13 @@ static bool type_match(struct hreg* hreg, struct vreg* vreg) | |||
| 
 | ||||
| static bool allocatable_stackable_input(struct hreg* hreg, struct vreg* vreg) | ||||
| { | ||||
|     return !pmap_findleft(current_ins, hreg) && | ||||
|     return !register_used(current_ins, hreg) && | ||||
|         type_match(hreg, vreg); | ||||
| } | ||||
| 
 | ||||
| static bool allocatable_stackable_output(struct hreg* hreg, struct vreg* vreg) | ||||
| { | ||||
|     return !pmap_findleft(current_outs, hreg) && | ||||
|     return !register_used(current_outs, hreg) && | ||||
|         type_match(hreg, vreg) && | ||||
|         !(hreg->attrs & current_hop->insndata->corrupts); | ||||
| } | ||||
|  | @ -295,7 +328,7 @@ static void add_output_register(struct vreg* vreg) | |||
| 
 | ||||
|         pmap_add(current_outs, hreg, vreg); | ||||
|         tracef('R', "R: output equality constraint requires extra move of %%%d => %s\n", | ||||
|             c->equals_to->id, hreg->name); | ||||
|             c->equals_to->id, hreg->id); | ||||
|         pmap_add(current_ins, hreg, c->equals_to); | ||||
|     } | ||||
|     else | ||||
|  | @ -332,7 +365,7 @@ static void add_through_register(struct vreg* vreg, struct hreg* hreg) | |||
|             /* Nope, can't honour the hint. Mark the register as evicted; we'll
 | ||||
|              * put it in something later (probably a stack slot). */ | ||||
| 
 | ||||
|             tracef('R', "R: cannot place %%%d in %s, evicting\n", vreg->id, hreg->name); | ||||
|             tracef('R', "R: cannot place %%%d in %s, evicting\n", vreg->id, hreg->id); | ||||
|             pmap_put(&evicted, vreg, hreg); | ||||
|             pmap_remove(current_ins, hreg, vreg); | ||||
|             pmap_remove(current_outs, hreg, vreg); | ||||
|  | @ -372,7 +405,7 @@ static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* s | |||
|     array_append(&hregs, hreg); | ||||
| 
 | ||||
| found: | ||||
|     tracef('R', "R: evicted %%%d moving to %s\n", vreg->id, hreg->name); | ||||
|     tracef('R', "R: evicted %%%d moving to %s\n", vreg->id, hreg->id); | ||||
|     pmap_add(current_ins, hreg, vreg); | ||||
|     pmap_add(current_outs, hreg, vreg); | ||||
| } | ||||
|  | @ -452,7 +485,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 if (hreg) | ||||
|                 { | ||||
|                     tracef('R', "R: import hreg %s for input %%%d from %s\n", | ||||
|                         hreg->name, vreg->id, prevbb->name); | ||||
|                         hreg->id, vreg->id, prevbb->name); | ||||
|                     assert(!pmap_findleft(old, hreg)); | ||||
|                     pmap_put(old, hreg, vreg); | ||||
|                     goto nextvreg; | ||||
|  | @ -482,7 +515,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 if (hreg && !pmap_findleft(old, hreg)) | ||||
|                 { | ||||
|                     tracef('R', "R: import hreg %s for phi input %%%d from %s\n", | ||||
|                         hreg->name, vreg->id, phi->prev->name); | ||||
|                         hreg->id, vreg->id, phi->prev->name); | ||||
|                     pmap_put(old, hreg, vreg); | ||||
|                 } | ||||
|             } | ||||
|  | @ -503,7 +536,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 struct hreg* hreg = allocate_phi_hreg(old, vreg, c->type); | ||||
| 
 | ||||
|                 tracef('R', "R: import fallback hreg %s for phi input %%%d from %s\n", | ||||
|                     hreg->name, vreg->id, phi->prev->name); | ||||
|                     hreg->id, vreg->id, phi->prev->name); | ||||
|                 pmap_add(old, hreg, vreg); | ||||
|             } | ||||
|         } | ||||
|  | @ -525,7 +558,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 struct vreg* vreg = hop->regsin.item[k].right; | ||||
|                 if (k != 0) | ||||
|                     tracef('R', " "); | ||||
|                 tracef('R', "%%%d=>%s", vreg->id, hreg->name); | ||||
|                 tracef('R', "%%%d=>%s", vreg->id, hreg->id); | ||||
|             } | ||||
|             tracef('R', "] ["); | ||||
|             for (k=0; k<hop->regsout.count; k++) | ||||
|  | @ -534,7 +567,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 struct vreg* vreg = hop->regsout.item[k].right; | ||||
|                 if (k != 0) | ||||
|                     tracef('R', " "); | ||||
|                 tracef('R', "%%%d=>%s", vreg->id, hreg->name); | ||||
|                 tracef('R', "%%%d=>%s", vreg->id, hreg->id); | ||||
|             } | ||||
|             tracef('R', "]\n"); | ||||
| 
 | ||||
|  | @ -551,9 +584,9 @@ static struct hop* create_swap(struct basicblock* bb, struct hreg* src, struct h | |||
|     struct hop* hop = new_hop(bb, NULL); | ||||
| 
 | ||||
|     hop_add_string_insel(hop, "! swap "); | ||||
|     hop_add_hreg_insel(hop, src); | ||||
|     hop_add_hreg_insel(hop, src, 0); | ||||
|     hop_add_string_insel(hop, " <-> "); | ||||
|     hop_add_hreg_insel(hop, dest); | ||||
|     hop_add_hreg_insel(hop, dest, 0); | ||||
|     hop_add_eoi_insel(hop); | ||||
| 
 | ||||
|     return hop; | ||||
|  | @ -661,7 +694,7 @@ static void insert_phi_copies(void) | |||
| 
 | ||||
|                     tracef('R', "R: map %%%d -> %%%d (%s)\n", | ||||
|                         phi->ir->result->id,  | ||||
|                         vreg->id, dest->name); | ||||
|                         vreg->id, dest->id); | ||||
| 
 | ||||
|                     pmap_put(&destregs, dest, phi->ir->result); | ||||
|                 } | ||||
|  |  | |||
|  | @ -12,11 +12,12 @@ struct vreg* new_vreg(void) | |||
| struct hreg* new_hreg(const struct burm_register_data* brd) | ||||
| { | ||||
| 	struct hreg* hreg = calloc(1, sizeof *hreg); | ||||
| 	hreg->name = brd->name; | ||||
|     hreg->realname = brd->realname; | ||||
| 	hreg->id = brd->id; | ||||
|     hreg->brd = brd; | ||||
|     hreg->type = brd->type; | ||||
| 	hreg->attrs = brd->attrs; | ||||
| 	hreg->is_stacked = false; | ||||
|     /* The aliases array needs to be initialised later. */ | ||||
| 	return hreg; | ||||
| } | ||||
| 
 | ||||
|  | @ -24,12 +25,12 @@ struct hreg* new_stacked_hreg(uint32_t type) | |||
| { | ||||
|     static int hreg_count = 1; | ||||
| 	struct hreg* hreg = calloc(1, sizeof *hreg); | ||||
| 	hreg->name = aprintf("stacked_%d_id_%d", type, hreg_count++); | ||||
|     hreg->realname = hreg->name; | ||||
| 	hreg->id = aprintf("stacked_%d_id_%d", type, hreg_count++); | ||||
|     hreg->type = type; | ||||
| 	hreg->attrs = type; | ||||
| 	hreg->is_stacked = true; | ||||
| 	hreg->offset = -1; | ||||
|     array_append(&hreg->aliases, hreg); | ||||
| 	return hreg; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,12 +13,13 @@ struct phicongruence | |||
| 
 | ||||
| struct hreg | ||||
| { | ||||
| 	const char* name; | ||||
|     const char* realname; | ||||
| 	const char* id; | ||||
|     const struct burm_register_data* brd; | ||||
|     uint32_t type; | ||||
| 	uint32_t attrs; | ||||
| 	bool is_stacked; | ||||
| 	int offset; | ||||
|     ARRAYOF(struct hreg) aliases; | ||||
| }; | ||||
| 
 | ||||
| struct vreg | ||||
|  |  | |||
|  | @ -495,6 +495,16 @@ static void insn_ivalue(int opcode, arith value) | |||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_sdl: | ||||
|             appendir( | ||||
|                 new_ir2( | ||||
|                     IR_STORE, EM_wordsize*2, | ||||
|                     new_localir(value), | ||||
|                     pop(EM_wordsize*2) | ||||
|                 ) | ||||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_lal: | ||||
|             push( | ||||
|                 new_localir(value) | ||||
|  | @ -972,6 +982,15 @@ static void insn_lvalue(int opcode, const char* label, arith offset) | |||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_lde: | ||||
|             push( | ||||
|                 new_ir1( | ||||
|                     IR_LOAD, EM_wordsize*2, | ||||
|                     address_of_external(label, offset) | ||||
|                 ) | ||||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_ste: | ||||
|             appendir( | ||||
|                 new_ir2( | ||||
|  | @ -982,6 +1001,16 @@ static void insn_lvalue(int opcode, const char* label, arith offset) | |||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_sde: | ||||
|             appendir( | ||||
|                 new_ir2( | ||||
|                     IR_STORE, EM_wordsize*2, | ||||
|                     address_of_external(label, offset), | ||||
|                     pop(EM_wordsize*2) | ||||
|                 ) | ||||
|             ); | ||||
|             break; | ||||
| 
 | ||||
|         case op_zre: | ||||
|             appendir( | ||||
|                 new_ir2( | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ extern int yylex(void); | |||
| %term EMIT | ||||
| %term EQUALS | ||||
| %term FRAGMENT | ||||
| %term NAMED | ||||
| %term NOTEQUALS | ||||
| %term PATTERNS | ||||
| %term PREFERS | ||||
|  | @ -44,7 +45,6 @@ extern int yylex(void); | |||
| %token <string>     ID | ||||
| %token <string>     QFRAGMENT | ||||
| 
 | ||||
| %type  <stringlist> aliases; | ||||
| %type  <constraint> constraint | ||||
| %type  <constraint> constraints | ||||
| %type  <expr>       predicate | ||||
|  | @ -55,6 +55,8 @@ extern int yylex(void); | |||
| %type  <rule>       pattern | ||||
| %type  <rule>       pattern_constraints | ||||
| %type  <rule>       pattern_emit | ||||
| %type  <stringlist> aliases; | ||||
| %type  <stringlist> names; | ||||
| %type  <stringlist> qfragments | ||||
| %type  <terminfo>   terminfo | ||||
| %type  <tree>       rhs | ||||
|  | @ -73,12 +75,18 @@ registers | |||
|     ; | ||||
| 
 | ||||
| register | ||||
|     : ID QFRAGMENT                    { $$ = makereg($1, $2); } | ||||
|     : ID                              { $$ = makereg($1); } | ||||
|     | register NAMED '(' names ')'    { $$ = $1; setregnames($$, $4); } | ||||
|     | register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); } | ||||
|     | register ID                     { $$ = $1; addregattr($1, $2, false); } | ||||
|     | register ID '!'                 { $$ = $1; addregattr($1, $2, true); } | ||||
|     ; | ||||
| 
 | ||||
| names | ||||
|     : QFRAGMENT                       { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); } | ||||
|     | names ',' QFRAGMENT             { $$ = $1; stringlist_add($$, $3); } | ||||
|     ; | ||||
| 
 | ||||
| aliases | ||||
|     : ID                              { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); } | ||||
|     | aliases ',' ID                  { $$ = $1; stringlist_add($$, $3); } | ||||
|  |  | |||
|  | @ -268,7 +268,7 @@ static void* install(const char* name) | |||
| 	return &p->sym; | ||||
| } | ||||
| 
 | ||||
| struct reg* makereg(const char* id, const char* realname) | ||||
| struct reg* makereg(const char* id) | ||||
| { | ||||
| 	struct reg* p = smap_get(®isters, id); | ||||
| 	static int number = 0; | ||||
|  | @ -277,7 +277,6 @@ struct reg* makereg(const char* id, const char* realname) | |||
| 		yyerror("redefinition of '%s'", id); | ||||
| 	p = calloc(1, sizeof(*p)); | ||||
| 	p->name = id; | ||||
| 	p->realname = realname; | ||||
| 	p->number = number++; | ||||
| 	array_append(&p->aliases, p); | ||||
| 	smap_put(®isters, id, p); | ||||
|  | @ -285,6 +284,14 @@ struct reg* makereg(const char* id, const char* realname) | |||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| void setregnames(struct reg* reg, struct stringlist* names) | ||||
| { | ||||
| 	if (reg->names) | ||||
| 		yyerror("you can only set one set of register names"); | ||||
| 
 | ||||
| 	reg->names = names; | ||||
| } | ||||
| 
 | ||||
| struct regattr* makeregattr(const char* id) | ||||
| { | ||||
| 	struct regattr* p = smap_get(®isterattrs, id); | ||||
|  | @ -629,14 +636,33 @@ static void emitregisters(void) | |||
| 		print("NULL\n};\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	for (i=0; i<registers.count; i++) | ||||
| 	{ | ||||
| 		struct reg* r = registers.item[i].right; | ||||
| 
 | ||||
| 		print("const char* %Pregister_names_%d_%s[] = {\n%1", i, r->name); | ||||
| 		if (r->names) | ||||
| 		{ | ||||
| 			struct stringfragment* f = r->names->first; | ||||
| 			while (f) | ||||
| 			{ | ||||
| 				print("\"%s\", ", f->data); | ||||
| 				f = f->next; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 			print("\"%s\", ", r->name); | ||||
| 		print("NULL\n};\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	print("const struct %Pregister_data %Pregister_data[] = {\n"); | ||||
| 	for (i=0; i<registers.count; i++) | ||||
| 	{ | ||||
| 		struct reg* r = registers.item[i].right; | ||||
| 		assert(r->number == i); | ||||
| 
 | ||||
| 		print("%1{ \"%s\", \"%s\", 0x%x, 0x%x, %Pregister_aliases_%d_%s },\n", | ||||
| 			r->name, r->realname, r->type, r->attrs, i, r->name); | ||||
| 		print("%1{ \"%s\", 0x%x, 0x%x, %Pregister_names_%d_%s, %Pregister_aliases_%d_%s },\n", | ||||
| 			r->name, r->type, r->attrs, i, r->name, i, r->name); | ||||
| 	} | ||||
| 	print("%1{ NULL }\n"); | ||||
| 	print("};\n\n"); | ||||
|  | @ -1215,14 +1241,18 @@ static void emitinsndata(Rule rules) | |||
| 		 | ||||
| 		while (f) | ||||
| 		{ | ||||
| 			switch (f->data[0]) | ||||
| 			char* data = strdup(f->data); | ||||
| 			int type = *data++; | ||||
| 			char* label = strtok(data, "."); | ||||
| 			char* nameindex_s = strtok(NULL, "."); | ||||
| 			int nameindex = nameindex_s ? atoi(nameindex_s) : 0; | ||||
| 
 | ||||
| 			switch (type) | ||||
| 			{ | ||||
| 				case '%': | ||||
| 				{ | ||||
| 					const char* label = f->data + 1; | ||||
| 
 | ||||
| 					if (r->label && (strcmp(label, r->label) == 0)) | ||||
| 						print("%1data->emit_return_reg();\n", label); | ||||
| 						print("%1data->emit_return_reg(%d);\n", nameindex); | ||||
| 					else | ||||
| 					{ | ||||
| 						Tree node; | ||||
|  | @ -1234,25 +1264,25 @@ static void emitinsndata(Rule rules) | |||
| 						if (nt->kind == NONTERM) | ||||
| 						{ | ||||
| 							if (nt->is_fragment) | ||||
| 								print("%1data->emit_fragment("); | ||||
| 								print("%1data->emit_fragment(%d);\n", index); | ||||
| 							else | ||||
| 								print("%1data->emit_reg("); | ||||
| 								print("%1data->emit_reg(%d, %d);\n", index, nameindex); | ||||
| 						} | ||||
| 						else | ||||
| 							print("%1data->emit_reg("); | ||||
| 
 | ||||
| 						print("%d);\n", index); | ||||
| 							print("%1data->emit_reg(%d, %d);\n", index, nameindex); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 
 | ||||
| 				case '$': | ||||
| 				{ | ||||
| 					const char* label = f->data + 1; | ||||
| 					int index = 0; | ||||
| 					if (!find_child_index(r->pattern, label, &index, NULL)) | ||||
| 						label_not_found(r, label); | ||||
| 
 | ||||
| 					if (nameindex != 0) | ||||
| 						yyerror("indices other than 0 make no sense for $-values"); | ||||
| 
 | ||||
| 					print("%1data->emit_value(%d);\n", index); | ||||
| 					break; | ||||
| 				} | ||||
|  |  | |||
|  | @ -59,10 +59,10 @@ struct terminfo | |||
| struct reg | ||||
| { | ||||
| 	const char* name;          /* friendly register name */ | ||||
| 	const char* realname;      /* name used in assembly output */ | ||||
| 	int number;                /* identifying number */ | ||||
| 	uint32_t attrs;            /* bitfield of register attributes */ | ||||
| 	uint32_t type;             /* register type */ | ||||
| 	struct stringlist* names;  /* register names */ | ||||
| 	ARRAYOF(struct reg) aliases; /* registers that this one aliases */ | ||||
| }; | ||||
| 
 | ||||
|  | @ -72,7 +72,8 @@ struct regattr | |||
| 	int number;            /* identifying number */ | ||||
| }; | ||||
| 
 | ||||
| extern struct reg* makereg(const char* name, const char* realname); | ||||
| extern struct reg* makereg(const char* name); | ||||
| extern void setregnames(struct reg* reg, struct stringlist* names); | ||||
| extern void addregattr(struct reg* reg, const char* regattr, bool exact); | ||||
| extern void addregaliases(struct reg* reg, struct stringlist* aliases); | ||||
| extern struct regattr* getregattr(const char* name); | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ S POPF | |||
| S LOAD # must be followed by float form | ||||
| S LOADF | ||||
| S STORE | ||||
| S STOREF | ||||
| 
 | ||||
| # Arithemetic operations | ||||
| S ADD | ||||
|  |  | |||
|  | @ -40,8 +40,8 @@ struct burm_emitter_data | |||
| { | ||||
|     void (*emit_string)(const char* data); | ||||
|     void (*emit_fragment)(int child); | ||||
|     void (*emit_return_reg)(void); | ||||
|     void (*emit_reg)(int child); | ||||
|     void (*emit_return_reg)(int index); | ||||
|     void (*emit_reg)(int child, int index); | ||||
|     void (*emit_value)(int child); | ||||
|     void (*emit_eoi)(void); | ||||
|     void (*constrain_input_reg)(int child, uint32_t attr); | ||||
|  | @ -63,10 +63,10 @@ extern const struct burm_instruction_data burm_instruction_data[]; | |||
| 
 | ||||
| struct burm_register_data | ||||
| { | ||||
|     const char* name; | ||||
|     const char* realname; | ||||
|     const char* id; | ||||
|     uint32_t type; | ||||
|     uint32_t attrs; | ||||
|     const char** names; | ||||
|     const struct burm_register_data** aliases; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ static int braces = 0; | |||
| <INITIAL>"\""               BEGIN(QSTRING); | ||||
| <QSTRING>"\""               BEGIN(INITIAL); | ||||
| 
 | ||||
| <QSTRING>[%$][a-zA-Z_][a-zA_Z_0-9]+ { | ||||
| <QSTRING>[%$][a-zA-Z_][a-zA_Z_0-9]+(\.[0-9]+)? { | ||||
|                                 yylval.string = strdup(yytext); | ||||
|                                 return QFRAGMENT; | ||||
|                             } | ||||
|  | @ -44,6 +44,7 @@ static int braces = 0; | |||
| "cost"                      return COST; | ||||
| "emit"                      return EMIT; | ||||
| "fragment"                  return FRAGMENT; | ||||
| "named"                     return NAMED; | ||||
| "prefers"                   return PREFERS; | ||||
| "when"                      return WHEN; | ||||
| "with"                      return WITH; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue