Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6446 GerdtR 1
#define _SWITCH_
2
 
3
 
4
 
5
extern int lastcommand;	//последний оператор в блоке
6
 
7
 
8
 
9
FSWI *swtables;	//таблица информаций об switch
10
 
11
 
12
 
13
int numexpandcase;
14
 
15
 
16
 
17
{
18
 
19
	if(shortjmp==FALSE){
20
 
21
		if(am32==FALSE)*(unsigned short *)&output[endsw-2]=(unsigned short)size;
22
 
23
	}
24
 
25
		if((unsigned int)size>127)jumperror(line,mes);
26
 
27
	}
28
 
29
 
30
 
31
{
32
 
33
		op66(tokr);         //CMP EAX,val
34
 
35
			op(0x85);
36
 
37
		}
38
 
39
			if(short_ok(value,tokr==r32?TRUE:FALSE)){
40
 
41
				op(0xF8+reg);
42
 
43
			}
44
 
45
				if(reg==0)op(0x3D);
46
 
47
					op(0x81);
48
 
49
				}
50
 
51
			}
52
 
53
	}
54
 
55
		if(value==0){
56
 
57
 
58
 
59
		else{
60
 
61
			else{
62
 
63
				op(0xF8+reg);
64
 
65
			op(value);
66
 
67
	}
68
 
69
70
 
71
{
72
 
73
int dtok,line,oinptr,i,otok2;
74
 
75
unsigned char *oinput;
76
 
77
78
 
79
int retcode=TRUE;
80
 
81
	otok=itok;
82
 
83
	line=linenum2;
84
 
85
	oinptr=inptr=inptr2;
86
 
87
//new
88
 
89
	oendinptr=endinptr;
90
 
91
		COM_MOD *pmod=cur_mod;
92
 
93
			pmod=pmod->next;
94
 
95
		input=pmod->input;
96
 
97
		endinptr=pmod->endinptr;
98
 
99
		inptr++;
100
 
101
102
 
103
		FastTok(0);
104
 
105
			SwTok(tk_openbrace);
106
 
107
		}
108
 
109
			for(i=1;i!=0;){
110
 
111
				if(tok==tk_question)CheckDir();
112
 
113
					case tk_eof:
114
 
115
						retcode=FALSE;
116
 
117
						break;
118
 
119
					case tk_closebrace: i--; break;
120
 
121
					case tk_case:
122
 
123
						if(i==1){
124
 
125
								inptr2=inptr;
126
 
127
								linenum2=linenumber;
128
 
129
								nexttok();
130
 
131
									if(*numcase==MAXCASE){
132
 
133
										retcode=FALSE;
134
 
135
									else{
136
 
137
 
138
 
139
												preerror("Duplicate 'case'");
140
 
141
												break;
142
 
143
										}
144
 
145
										if(tok==tk_multipoint){
146
 
147
											nexttok();
148
 
149
											numexpandcase+=val-(caseinf+*numcase)->value-1;
150
 
151
												preerror("The first value 'case' should be smaller");
152
 
153
 
154
 
155
											(caseinf+*numcase)->type=endmulti;
156
 
157
											(caseinf+*numcase)->postcase=(caseinf+*numcase-1)->postcase;
158
 
159
										else (caseinf+*numcase)->type=singlcase;
160
 
161
									}
162
 
163
								else{
164
 
165
									retcode=FALSE;
166
 
167
								inptr=inptr2;
168
 
169
							}
170
 
171
						break;
172
 
173
			}
174
 
175
	}
176
 
177
		tok=dtok;
178
 
179
		linenum2=line;
180
 
181
		inptr2=oinptr;
182
 
183
	}
184
 
185
		inptr2=inptr;
186
 
187
		linenum2=linenumber;
188
 
189
//new
190
 
191
	endinptr=oendinptr;
192
 
193
	return retcode;
194
 
195
196
 
197
{
198
 
199
int numcase=0,reg=AX,mode=0;
200
 
201
 
202
 
203
REGISTERSTAT *bakregstat,*changeregstat;
204
 
205
//new
206
 
207
unsigned char oinline=useinline;
208
 
209
ITOK otok;
210
 
211
unsigned long numbervar;
212
 
213
int nonum;
214
 
215
	useinline=0;
216
 
217
	numexpandcase=0;
218
 
219
	getoperand();
220
 
221
	expecting(tk_openbracket);
222
 
223
		case tk_intvar:
224
 
225
			goto dint;
226
 
227
			signflag=1;
228
 
229
			getoperand();
230
 
231
		case tk_reg:
232
 
233
			tokr=r16;
234
 
235
		case tk_charvar:
236
 
237
			goto dchar;
238
 
239
			signflag=1;
240
 
241
			getoperand();
242
 
243
		case tk_beg:
244
 
245
			tokr=r8;
246
 
247
		case tk_long:
248
 
249
		case tk_dword:
250
 
251
			goto dlong;
252
 
253
			getoperand();
254
 
255
		case tk_floatvar:
256
 
257
		case tk_dwordvar:
258
 
259
dlong:
260
 
261
			break;
262
 
263
		case tk_qwordvar:
264
 
265
			tokr=r64;
266
 
267
		case tk_openbracket:
268
 
269
			if(tok>=tk_char&&tok<=tk_double){
270
 
271
				switch(tok){
272
 
273
					case tk_float:
274
 
275
					case tk_int:
276
 
277
						signflag=1;
278
 
279
			}
280
 
281
			expectingoperand(tk_closebracket);
282
 
283
		default:
284
 
285
			break;
286
 
287
#ifdef OPTVARCONST
288
 
289
		otok=itok;
290
 
291
	}
292
 
293
	if(ScanSwitch(&numcase,caseinf,startmod)){
294
 
295
unsigned int sizetab;	//размер таблицы
296
 
297
unsigned int size0=0,size1;
298
 
299
long smin=0x7fffffff,smax=-0x7fffffff;
300
 
301
unsigned oaddESP=addESP;
302
 
303
			if(!optimizespeed){
304
 
305
				else if(tokr==r8)size0=numcase*2;
306
 
307
					reg0=itok.number;	//предполагаемый регистр метода 0
308
 
309
			for(i=0;i
310
 
311
				if((caseinf+i)->valuevalue;
312
 
313
				if((long) (caseinf+i)->valuevalue;
314
 
315
					if((caseinf+i)->value==0)size0+=2;
316
 
317
					else{
318
 
319
						if(am32)size0+=2;
320
 
321
				}
322
 
323
					if((caseinf+i)->postcase==0)size0+=(am32==FALSE?(chip<3?5:4):6);
324
 
325
				}
326
 
327
			if((unsigned int)(smax-smin)<(max-min)){
328
 
329
				svop=8;
330
 
331
			}
332
 
333
				smin=min;
334
 
335
			}
336
 
337
			if(sizetab<0x1000000&&(!(am32==FALSE&&tokr==r32))){
338
 
339
					if((unsigned int)(sizetab/numcase)<(unsigned int)(am32==FALSE?3:4)){
340
 
341
						if(am32==FALSE)reg=BX;
342
 
343
					 3 для 16-битного режима и 4 для 32-битного, то берется метод 1 */
344
 
345
				}
346
 
347
					if(shortjmp)size0+=2;
348
 
349
					size1=sizetab*(am32==FALSE?2:4);
350
 
351
					if(max>127&®0==AX)size1--;
352
 
353
						if(min==1)size1++;
354
 
355
						else if(min<128)size1+=3;
356
 
357
							size1+=(am32==FALSE?4:6);
358
 
359
						}
360
 
361
					size1+=(am32==FALSE?6:9);
362
 
363
						if(tokr!=r32)size1+=3;
364
 
365
					}
366
 
367
						if(reg0!=BX)size1+=2;
368
 
369
				//выбор метода с меньшим размером
370
 
371
						mode=1;
372
 
373
						if(am32==FALSE)reg=BX;
374
 
375
					}
376
 
377
			}
378
 
379
		if(numcase>9&&(!optimizespeed)){
380
 
381
			size2=numcase+numexpandcase;
382
 
383
 
384
 
385
					else size2=size2*3+8;
386
 
387
				case r16:
388
 
389
 
390
 
391
				case r32:
392
 
393
					else size2=size2*6+9;
394
 
395
			}
396
 
397
			//выбор метода с меньшим размером
398
 
399
		}
400
 
401
		if(mode==2){
402
 
403
			reg0=idxregs[1];
404
 
405
				if(tokr==r8)doalmath(signflag,&ofsstr);
406
 
407
			}
408
 
409
				reg=itok.number;
410
 
411
				nexttok();
412
 
413
				ClearReg(reg);
414
 
415
			warningreg(regs[am32][reg0]);
416
 
417
		else if((tok==tk_beg||tok==tk_reg||tok==tk_reg32)&&tok2==tk_closebracket){
418
 
419
				reg=itok.number;
420
 
421
				else nexttok();
422
 
423
			}
424
 
425
				getintoreg_32(BX,r16,0,&ofsstr);
426
 
427
				warningreg("BX");
428
 
429
		}
430
 
431
			if(tokr==r8)doalmath(signflag,&ofsstr);
432
 
433
			if(reg!=AX){
434
 
435
				if(tokr==r8)outword(0xB4);	//mov ah,0
436
 
437
				else op(0x93);	//xchg ax,bx
438
 
439
			else{
440
 
441
				if(mode&&am32&&tokr!=r32){
442
 
443
					op(tokr==r8?0xB6:0xB7);
444
 
445
				}
446
 
447
		}
448
 
449
		if(numcase){
450
 
451
				if(min!=0){
452
 
453
					else if(min==2&&(!optimizespeed)){
454
 
455
						op(0x48+reg-svop);	//dec reg
456
 
457
					else if(min<128){
458
 
459
						op(0xE8+reg-svop*5);
460
 
461
					}
462
 
463
						if(reg==AX)op(0x2D-svop*5);
464
 
465
							op(0x81);
466
 
467
						}
468
 
469
						else outword(min);
470
 
471
					if(am32)warningreg(regs[1][reg]);
472
 
473
				if(max<128){
474
 
475
					op(0xF8+reg);
476
 
477
				}
478
 
479
					if(reg==AX)op(0x3D);
480
 
481
						op(0x81);
482
 
483
					}
484
 
485
					else outword(max);
486
 
487
				if(shortjmp==FALSE){
488
 
489
						outword(0x376);	//jbe 3
490
 
491
					}
492
 
493
					outword(0);
494
 
495
				}
496
 
497
					op(0x77);
498
 
499
				}
500
 
501
				if(am32){
502
 
503
					op(0x85+reg*8);
504
 
505
				else outdword(0xA7FFDB01);	//add bx,bx jmp [bx+table]
506
 
507
				size1=outptr;
508
 
509
				if(am32)outword(0);
510
 
511
			else if(mode==0){
512
 
513
				for(;numcase>0;){	//ветвление
514
 
515
					CmpRegNum(tokr,(caseinf+numcase)->value,reg);
516
 
517
						if(numcase){
518
 
519
								if(chip<3){
520
 
521
									op(0xE9);	//jmp to default
522
 
523
								else outword(0x840F);	//jz default
524
 
525
								if(am32)outword(0);
526
 
527
							else outword(0x74);
528
 
529
						}
530
 
531
							if(shortjmp==FALSE){
532
 
533
									outword(0x374);	//jnz 3
534
 
535
								}
536
 
537
								outword(0);
538
 
539
							}
540
 
541
							endsw=outptr;	//адрес конца switch или default
542
 
543
					}
544
 
545
						numcase--;
546
 
547
						if(numcase!=0){
548
 
549
								if(max==0){
550
 
551
										outdword(0x860F);
552
 
553
									}
554
 
555
										outword(am32==FALSE?0x0377:0x577);
556
 
557
									}
558
 
559
								else{
560
 
561
									endsw=outptr;
562
 
563
									if(chip>2){
564
 
565
										if(am32)outword(0);
566
 
567
									else{
568
 
569
										jumploc0();
570
 
571
									output[endsw-1]=(unsigned char)(outptr-endsw);
572
 
573
							}
574
 
575
								if(max==0)outword(0x76);
576
 
577
									outword(0x77);
578
 
579
									CmpRegNum(tokr,max,reg);
580
 
581
									output[endsw-1]=(unsigned char)(outptr-endsw);
582
 
583
							}
584
 
585
						}
586
 
587
							if(shortjmp==FALSE){
588
 
589
									outdword(0x870F);
590
 
591
									if(max!=0){
592
 
593
										CmpRegNum(tokr,max,reg);
594
 
595
										if(am32)outword(0);
596
 
597
								}
598
 
599
									if(max==0) outword(am32==FALSE?0x0376:0x576);
600
 
601
										outword(0x77);
602
 
603
										CmpRegNum(tokr,max,reg);
604
 
605
										output[endsw]=(unsigned char)(outptr-endsw-1);
606
 
607
									jumploc0();
608
 
609
							}
610
 
611
								outword(0x77);
612
 
613
									endsw2=outptr;
614
 
615
									outword(0x72);
616
 
617
							}
618
 
619
						}
620
 
621
				}
622
 
623
			else if(mode==2){
624
 
625
					outdword(0x071E0651);	//push cx,es,ds pop es
626
 
627
					outword(numcase+numexpandcase);
628
 
629
					AddReloc(CS);
630
 
631
					outword(0);
632
 
633
					switch(tokr){
634
 
635
						case r32: op(0x66);
636
 
637
					}
638
 
639
					op(shortjmp==FALSE?4:3);
640
 
641
					if(shortjmp==FALSE)jumploc0();
642
 
643
					endsw=outptr;	//адрес конца switch или default
644
 
645
					outword(numcase+numexpandcase);
646
 
647
					op(0xFF);
648
 
649
					AddReloc(CS);
650
 
651
					outword(0);
652
 
653
					outword(0x25FF);	//jmp [di]
654
 
655
				else{
656
 
657
					op(0xC0+reg0*9);	//xor reg0,reg0
658
 
659
						case r8: op(0x38); op(0x4+reg*8); op(5+reg0*8); break;
660
 
661
						case r16: op(0x66); op(0x39); op(0x4+reg*8); op(0x45+reg0*8); break;
662
 
663
					AddReloc(CS);
664
 
665
					outdword(0);
666
 
667
					outword(0x24FF);	//jmp [reg0*4+tableadr]
668
 
669
					AddReloc(CS);
670
 
671
					outdword(0);
672
 
673
					if((numcase+numexpandcase)>127){	//cmp reg0,numcase
674
 
675
						op(0xF8+reg0);
676
 
677
					}
678
 
679
						op(0x83);
680
 
681
						op(numcase+numexpandcase);
682
 
683
					op(0x72);
684
 
685
					else op(tokr==r16?0xE9:0xEA);
686
 
687
					else outword(0xEB);
688
 
689
				}
690
 
691
		}
692
 
693
		useinline=oinline;
694
 
695
		changeregstat=BakRegStat();
696
 
697
		do{
698
 
699
				RestoreStack();
700
 
701
				switch(lastcommand){
702
 
703
					case tk_GOTO:
704
 
705
					case tk_BREAK:
706
 
707
					case tk_RETURN:
708
 
709
						CopyRegStat(bakregstat);
710
 
711
						nonum=FALSE;
712
 
713
						addESP=oaddESP;
714
 
715
					default:
716
 
717
#ifdef OPTVARCONST
718
 
719
#endif
720
 
721
						break;
722
 
723
				if(tok==tk_default){	//тоже для default
724
 
725
						if(numcase==0)jumploc0();	//default самый первый
726
 
727
						if(endsw2)CheckJmpSW(sline,endsw2,outptr,shortjmp,mesSWITCH);
728
 
729
					if(defaul)preerror("Duplicate 'default'");
730
 
731
					nexttok();
732
 
733
					continue;
734
 
735
				if(mode==0){
736
 
737
						if(am32==FALSE)*(unsigned short *)&output[defaul-2]=(unsigned short)(outptr-defaul);
738
 
739
					}
740
 
741
				}
742
 
743
				lastcommand=tok;	//new 12.12.07 14:27
744
 
745
#ifdef OPTVARCONST
746
 
747
 
748
 
749
#else
750
 
751
#endif
752
 
753
				if(tok==tk_multipoint){
754
 
755
					(caseinf+numcase)->value=doconstlongmath()-(mode==1?smin:0);
756
 
757
				}
758
 
759
				else if(swvar&&nonum==FALSE)Const2Var(&otok,numbervar,numrm);
760
 
761
				expecting(tk_colon);	//пров на : и чтение следующ tok
762
 
763
				continue;//goto checkcase;
764
 
765
			startblock();
766
 
767
			endblock();
768
 
769
		RestoreStack();
770
 
771
			switch(lastcommand){
772
 
773
					posts--;
774
 
775
					break;
776
 
777
					posts--;
778
 
779
					break;
780
 
781
		}
782
 
783
			if(mode==0&&svop){
784
 
785
				CheckJmpSW(sline,endsw,outptr,shortjmp,mesSWITCH);
786
 
787
			}
788
 
789
		}
790
 
791
		CompareRegStat(changeregstat);
792
 
793
		CopyRegStat(changeregstat);
794
 
795
		if(numcase){
796
 
797
				if(defaul==0){
798
 
799
					if(endsw2)CheckJmpSW(sline,endsw2,outptr,shortjmp,mesSWITCH);
800
 
801
				free(caseinf);
802
 
803
			else{
804
 
805
				CheckJmpSW(sline,endsw,defaul,shortjmp,mesSWITCH);
806
 
807
				if(!numswtable)swtables=(FSWI *)MALLOC(sizeof(FSWI));
808
 
809
				FSWI *swt=swtables+numswtable;
810
 
811
				swt->sizetab=(mode==2?numcase:sizetab)+numexpandcase;
812
 
813
				swt->numcase=numcase;
814
 
815
				swt->ptb=size1;
816
 
817
				swt->mode=mode;
818
 
819
				numswtable++;
820
 
821
		}
822
 
823
		SetBreakLabel();
824
 
825
	}
826
 
827
	lastcommand=tk_switch;
828
 
829
}
830
 
831
>
832
 
833
>
834
 
835
>
836
 
837
>
838
 
839
>
840
 
841
>
842
 
843
>
844
 
845
>
846
 
847
>
848
 
849
>
850