source: dev/trunk/ab5.0/abdev/compiler_x86/x86CodeGenerator.cpp@ 551

Last change on this file since 551 was 551, checked in by dai_9181, 16 years ago

・PutWithScheduleメソッドを追加。
・NativeCodeクラスが持つCompilerクラスへの依存度を除去した。

File size: 33.0 KB
Line 
1#include "stdafx.h"
2
3#include <Procedure.h>
4#include <CodeGenerator.h>
5
6
7
8/////////////////////////////////////////////////
9// ModR/Mバイト、SIBバイト、ディスプレースメント
10/////////////////////////////////////////////////
11
12//スケール
13#define SCALE_NON (char)0x00
14#define SCALE_2 (char)0x40
15#define SCALE_4 (char)0x80
16#define SCALE_8 (char)0xC0
17
18//インデックスなし
19#define INDEX_NON 0x04
20
21const PertialSchedule * CodeGenerator::set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType, bool isPertialSchedule )
22{
23 const PertialSchedule *pPertialSchedule = NULL;
24
25 // エラーチェック
26 if( ! ( mod == MOD_BASE
27 || mod == MOD_DISP32
28 || mod == MOD_BASE_DISP8
29 || mod == MOD_BASE_DISP32
30 || mod == MOD_REG ) )
31 {
32 compiler.errorMessenger.OutputFatalError();
33 }
34 if( isPertialSchedule && !( mod == MOD_DISP32 || mod == MOD_BASE_DISP32 ) )
35 {
36 compiler.errorMessenger.OutputFatalError();
37 }
38
39 if(mod==MOD_DISP32){
40 //ModR/Mバイト
41 pNativeCode->Put( (char)(REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(0x04)) );
42
43 base_reg=0x05;
44 index_reg=INDEX_NON;
45 }
46 else{
47 //ModR/Mバイト
48 pNativeCode->Put( (char)(mod | REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(base_reg)) );
49 }
50
51
52 //レジスタモードの場合は、ここで終了
53 if(mod==MOD_REG) return pPertialSchedule;
54
55
56 if(REGISTER_OPERAND(base_reg)==0x04||mod==MOD_DISP32){
57 //////////////////////
58 // SIBバイトを使う
59 //////////////////////
60
61 pNativeCode->Put( (char)(scale| REGISTER_OPERAND(index_reg)<<3 | REGISTER_OPERAND(base_reg)) );
62 }
63
64 //ディスプレースメントを必要としない場合は、ここで終了
65 if(mod==MOD_BASE) return pPertialSchedule;
66
67
68 //////////////////////////
69 // ディスプレースメント
70 //////////////////////////
71
72 if(mod==MOD_BASE_DISP8)
73 {
74 pNativeCode->Put( (char)disp );
75 }
76 else
77 {
78 if( isPertialSchedule )
79 {
80 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
81 pPertialSchedule = pertialSchedules.back();
82 }
83
84 this->PutWithSchedule( disp, scheduleType );
85 }
86
87 return pPertialSchedule;
88}
89
90
91
92void CodeGenerator::__op_format(char op_prefix,char opcode,int reg){
93 //命令プリフィックス
94 if(op_prefix)
95 {
96 pNativeCode->Put( op_prefix );
97 }
98
99 //オペコード、レジスタ
100 pNativeCode->Put( (char)(opcode|REGISTER_OPERAND(reg)) );
101}
102const PertialSchedule *CodeGenerator::__op_format(char op_prefix,char opcode1,char opcode2,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){
103 //命令プリフィックス
104 if(op_prefix)
105 {
106 pNativeCode->Put( op_prefix );
107 }
108
109 //オペコード
110 pNativeCode->Put( opcode1 );
111 if(opcode2)
112 {
113 pNativeCode->Put( opcode2 );
114 }
115
116 //ModR/M, SIB, disp
117 return set_mod_rm_sib_disp(mod,reg,SCALE_NON,INDEX_NON,base_reg,offset, scheduleType, isPertialSchedule );
118}
119
120
121
122///////////////////
123// mov関連
124///////////////////
125
126const PertialSchedule *CodeGenerator::op_mov_MV( int op_size, int base_reg, long offset, Schedule::Type offsetScheduleType, bool isPertialSchedule, long value, Schedule::Type valueScheduleType )
127{
128 //mov ptr[base_reg+offset],value
129 const PertialSchedule *pPertialSchedule = NULL;
130
131 if( op_size == sizeof(char) )
132 {
133 pNativeCode->Put( (char)0xC6 );
134 pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) );
135
136 if( isPertialSchedule )
137 {
138 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
139 pPertialSchedule = pertialSchedules.back();
140 }
141 this->PutWithSchedule( offset, offsetScheduleType );
142
143 pNativeCode->Put( (char)value );
144 }
145 else if( op_size == sizeof(short) )
146 {
147 pNativeCode->Put( (char)0x66 );
148 pNativeCode->Put( (char)0xC7 );
149 pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) );
150
151 if( isPertialSchedule )
152 {
153 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
154 pPertialSchedule = pertialSchedules.back();
155 }
156 this->PutWithSchedule( offset, offsetScheduleType );
157
158 pNativeCode->Put( (short)value );
159 }
160 else if( op_size == sizeof(long) )
161 {
162 pNativeCode->Put( (char)0xC7 );
163 pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) );
164
165 if( isPertialSchedule )
166 {
167 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
168 pPertialSchedule = pertialSchedules.back();
169 }
170 this->PutWithSchedule( offset, offsetScheduleType );
171
172 this->PutWithSchedule( value, valueScheduleType );
173 }
174
175 return pPertialSchedule;
176}
177const PertialSchedule *CodeGenerator::op_mov_RV(int reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){
178 //mov reg,value
179
180 //オペコード、レジスタ
181 pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) );
182
183 //DISP32
184 const PertialSchedule *pPertialSchedule = NULL;
185 if( isPertialSchedule )
186 {
187 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
188 pPertialSchedule = pertialSchedules.back();
189 }
190 this->PutWithSchedule( offset, scheduleType );
191
192 return pPertialSchedule;
193}
194void CodeGenerator::op_mov_RR(int reg1,int reg2){
195 //mov reg1,reg2
196
197 if(reg1==reg2) return;
198
199 //1000 1011 11xx xbbb
200 pNativeCode->Put( (char)0x8B );
201 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) );
202}
203const PertialSchedule *CodeGenerator::op_mov_RM(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){
204 //mov reg32,dword ptr[base_reg+offset]
205 //mov reg16,word ptr[base_reg+offset]
206 //mov reg8,byte ptr[base_reg+offset]
207
208 //16ビット演算の命令プリフィックス
209 char op_prefix=0;
210 if(op_size==sizeof(short)) op_prefix=(char)0x66;
211
212 //オペコード
213 char opcode;
214 if(op_size==sizeof(char)) opcode=(char)0x8A;
215 else opcode=(char)0x8B;
216
217 return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule );
218}
219const PertialSchedule *CodeGenerator::op_mov_RM_ex(int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){
220 //mov reg32,dword ptr[base_reg1+base_reg2+offset]
221 //mov reg16,word ptr[base_reg1+base_reg2+offset]
222 //mov reg8,byte ptr[base_reg1+base_reg2+offset]
223 const PertialSchedule *pPertialSchedule = NULL;
224
225 if(base_reg1==REG_ESP){
226 //SIBバイトのindex部にespは指定できない
227 base_reg1=base_reg2;
228 base_reg2=REG_ESP;
229 }
230
231 //16ビット演算のプリフィックス
232 if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 );
233
234 //オペコード
235 if(op_size==sizeof(char)) pNativeCode->Put( (char)0x8A );
236 else pNativeCode->Put( (char)0x8B );
237
238 if(bUseOffset){
239 ///////////////////////////
240 // オフセット値を使う
241 ///////////////////////////
242
243 //レジスタ
244 pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) );
245
246 //ベースレジスタ
247 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
248
249 //オフセット値
250 if( isPertialSchedule )
251 {
252 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
253 pPertialSchedule = pertialSchedules.back();
254 }
255 this->PutWithSchedule( offset, scheduleType );
256 }
257 else{
258 ///////////////////////////
259 // オフセット値を使わない
260 ///////////////////////////
261
262 //レジスタ
263 pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) );
264
265 //ベースレジスタ
266 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
267 }
268 return pPertialSchedule;
269}
270const PertialSchedule *CodeGenerator::op_mov_MR(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){
271 //mov dword ptr[base_reg+offset],reg32
272 //mov word ptr[base_reg+offset],reg16
273 //mov byte ptr[base_reg+offset],reg8
274
275 //16ビット演算の命令プリフィックス
276 char op_prefix=0;
277 if(op_size==sizeof(short)) op_prefix=(char)0x66;
278
279 //オペコード
280 char opcode;
281 if(op_size==sizeof(char)) opcode=(char)0x88;
282 else opcode=(char)0x89;
283
284 return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule );
285}
286const PertialSchedule *CodeGenerator::op_mov_MR_ex(int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){
287 //mov dword ptr[base_reg1+base_reg2+offset],reg32
288 //mov word ptr[base_reg1+base_reg2+offset],reg16
289 //mov byte ptr[base_reg1+base_reg2+offset],reg8
290 const PertialSchedule *pPertialSchedule = NULL;
291
292 if(base_reg1==REG_ESP){
293 //SIBバイトのindex部にrspは指定できない
294 base_reg1=base_reg2;
295 base_reg2=REG_ESP;
296 }
297
298 //16ビット演算のプリフィックス
299 if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 );
300
301 //オペコード
302 if(op_size==sizeof(char)) pNativeCode->Put( (char)0x88 );
303 else pNativeCode->Put( (char)0x89 );
304
305 if(bUseOffset==USE_OFFSET){
306 //////////////////////////
307 //オフセット値を使う
308 //////////////////////////
309
310 //レジスタ
311 pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) );
312
313 //ベースレジスタ
314 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
315
316 //オフセット値
317 if( isPertialSchedule )
318 {
319 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
320 pPertialSchedule = pertialSchedules.back();
321 }
322 this->PutWithSchedule( offset, scheduleType );
323 }
324 else{
325 //////////////////////////
326 //オフセット値を使わない
327 //////////////////////////
328
329 //レジスタ
330 pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) );
331
332 //ベースレジスタ
333 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
334 }
335 return pPertialSchedule;
336}
337
338
339
340
341////////////////////////////////
342// movsx関連
343////////////////////////////////
344
345void CodeGenerator::op_movsx_R32R16(int reg32,int reg16){
346 //movsx reg32,reg16
347
348 if( reg16 == REG_NON )
349 {
350 reg16 = reg32;
351 }
352
353 //16ビット演算の命令プリフィックス
354 char op_prefix=0;
355
356 //オペコード
357 char opcode=(char)0x0F;
358 char opcode2=(char)0xBF;
359
360 __op_format(op_prefix,opcode,opcode2,reg32,reg16,0,MOD_REG);
361}
362void CodeGenerator::op_movsx_R32R8(int reg32,int reg8){
363 //movsx reg32,reg8
364
365 if( reg8 == REG_NON )
366 {
367 reg8 = reg32;
368 }
369
370 //16ビット演算の命令プリフィックス
371 char op_prefix=0;
372
373 //オペコード
374 char opcode=(char)0x0F;
375 char opcode2=(char)0xBE;
376
377 __op_format(op_prefix,opcode,opcode2,reg32,reg8,0,MOD_REG);
378}
379void CodeGenerator::op_movsx_R16R8(int reg16,int reg8){
380 //movsx reg16,reg8
381
382 if( reg8 == REG_NON )
383 {
384 reg8 = reg16;
385 }
386
387 //16ビット演算の命令プリフィックス
388 char op_prefix=(char)0x66;
389
390 //オペコード
391 char opcode=(char)0x0F;
392 char opcode2=(char)0xBE;
393
394 __op_format(op_prefix,opcode,opcode2,reg16,reg8,0,MOD_REG);
395}
396
397
398
399//////////////////////////////////
400// lea関連
401//////////////////////////////////
402
403const PertialSchedule *CodeGenerator::op_lea_RM( int reg, int base_reg, long offset, char mod, Schedule::Type scheduleType, bool isPertialSchedule )
404{
405 //16ビット演算の命令プリフィックス
406 char op_prefix=0;
407
408 //オペコード
409 char opcode=(char)0x8D;
410
411 return __op_format( op_prefix, opcode, 0, reg, base_reg, offset, mod, scheduleType, isPertialSchedule );
412}
413
414
415
416//////////////////////////////////
417// インクリメント・デクリメント
418//////////////////////////////////
419
420void CodeGenerator::op_inc(int reg){
421 //inc reg
422
423 //16ビット演算の命令プリフィックス
424 char op_prefix=0;
425
426 //オペコード
427 char opcode=(char)0xFF;
428
429 __op_format(op_prefix,opcode,0,0,reg,0,MOD_REG);
430}
431void CodeGenerator::op_dec(int reg){
432 //dec reg
433
434 //16ビット演算の命令プリフィックス
435 char op_prefix=0;
436
437 //オペコード
438 char opcode=(char)0xFF;
439
440 __op_format(op_prefix,opcode,0,0x01,reg,0,MOD_REG);
441}
442
443
444
445/////////////////////
446// add関連
447/////////////////////
448
449void CodeGenerator::op_add_RV8(int reg,char cValue){
450 //add reg,value8
451
452 pNativeCode->Put( (char)0x83 );
453 pNativeCode->Put( (char)(0xC0|REGISTER_OPERAND(reg)) );
454 pNativeCode->Put( cValue );
455}
456const PertialSchedule *CodeGenerator::op_add_RV( int reg, long offset, Schedule::Type scheduleType, bool isPertialSchedule )
457{
458 // add reg,offset
459 const PertialSchedule *pPertialSchedule = NULL;
460
461 if( reg == REG_EAX )
462 {
463 // eaxのみ特殊
464 pNativeCode->Put( (char)0x05 );
465 }
466 else
467 {
468 pNativeCode->Put( (char)0x81 );
469 pNativeCode->Put( (char)(0xC0|REGISTER_OPERAND(reg)) );
470 }
471
472 // オフセット値
473 if( isPertialSchedule )
474 {
475 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
476 pPertialSchedule = pertialSchedules.back();
477 }
478 this->PutWithSchedule( offset, scheduleType );
479
480 return pPertialSchedule;
481}
482void CodeGenerator::op_add_RR( int reg1, int reg2 )
483{
484 //16ビット演算の命令プリフィックス
485 char op_prefix=0;
486
487 //オペコード
488 char opcode = (char)0x03;
489
490 __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG);
491}
492const PertialSchedule *CodeGenerator::op_add_RM(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){
493 //add reg32,dword ptr[base_reg+offset]
494 //add reg16,word ptr[base_reg+offset]
495 //add reg8,byte ptr[base_reg+offset]
496
497 //16ビット演算の命令プリフィックス
498 char op_prefix=0;
499 if(op_size==sizeof(short)) op_prefix=(char)0x66;
500
501 //オペコード
502 char opcode;
503 if(op_size==sizeof(char)) opcode=(char)0x02;
504 else opcode=(char)0x03;
505
506 return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule );
507}
508void CodeGenerator::op_adc_RV8(int reg,char cValue){
509 //adc reg,value8
510
511 pNativeCode->Put( (char)0x83 );
512 pNativeCode->Put( (char)(0xD0|REGISTER_OPERAND(reg)) );
513 pNativeCode->Put( cValue );
514}
515void CodeGenerator::op_adc_RR( int reg1, int reg2 )
516{
517 // adc reg1, reg2
518
519 //16ビット演算の命令プリフィックス
520 char op_prefix=0;
521
522 //オペコード
523 char opcode = (char)0x13;
524
525 __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG );
526}
527
528
529/////////////////////
530// sub関連
531/////////////////////
532
533void CodeGenerator::op_sub_RV8(int reg,char cValue){
534 //sub reg,value8
535
536 pNativeCode->Put( (char)0x83 );
537 pNativeCode->Put( (char)(0xE8|REGISTER_OPERAND(reg)) );
538 pNativeCode->Put( cValue );
539}
540void CodeGenerator::op_sub_RR( int reg1, int reg2 )
541{
542 // sub reg1, reg2
543
544 //16ビット演算の命令プリフィックス
545 char op_prefix=0;
546
547 //オペコード
548 char opcode = (char)0x2B;
549
550 __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG );
551}
552void CodeGenerator::op_sbb_RV8(int reg,char cValue){
553 //sbb reg,value8
554
555 pNativeCode->Put( (char)0x83 );
556 pNativeCode->Put( (char)(0xD8|REGISTER_OPERAND(reg)) );
557 pNativeCode->Put( cValue );
558}
559void CodeGenerator::op_sbb_RR( int reg1, int reg2 ){
560 //sbb reg1,reg2
561
562 //16ビット演算の命令プリフィックス
563 char op_prefix=0;
564
565 //オペコード
566 char opcode = (char)0x1B;
567
568 __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG );
569}
570
571
572
573////////////////////////
574// imul関連
575////////////////////////
576
577void CodeGenerator::op_imul_RR(int reg1,int reg2){
578 //imul reg1,reg2
579
580 //命令プリフィックス
581 char op_prefix = (char)0x0F;
582
583 //オペコード
584 char opcode = (char)0xAF;
585
586 __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG );
587}
588
589void CodeGenerator::op_imul_RV(int reg,long i32data){
590 //imul reg,i32data
591
592 if(-128<=i32data&&i32data<=127){
593 //オペコード
594 pNativeCode->Put( (char)0x6B );
595
596 //レジスタ
597 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) );
598
599 //値
600 pNativeCode->Put( (char)i32data );
601 }
602 else{
603 //オペコード
604 pNativeCode->Put( (char)0x69 );
605
606 //レジスタ
607 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) );
608
609 //値
610 pNativeCode->Put( i32data );
611 }
612}
613void CodeGenerator::op_imul_RV8(int reg,char cValue)
614{
615 //オペコード
616 pNativeCode->Put( (char)0x6B );
617
618 //レジスタ
619 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) );
620
621 //値
622 pNativeCode->Put( cValue );
623}
624
625
626
627//////////////////////
628// div関連
629//////////////////////
630
631void CodeGenerator::op_div_R( int reg )
632{
633 //div reg (eax=eax/reg...edx)
634 __op_format( (char)0xF7, (char)0xF0, reg );
635}
636void CodeGenerator::op_idiv_R( int reg )
637{
638 //idiv reg (eax=eax/reg...edx)
639 __op_format( (char)0xF7, (char)0xF8, reg );
640}
641
642
643
644//////////////////////
645// and関連
646//////////////////////
647
648void CodeGenerator::op_and_RV(int reg,long value){
649 //and reg,value
650
651 if(reg==REG_RAX){
652 //eaxのみ特殊
653
654 // [8bit rex] 0010 0101 [32bit offset]
655 pNativeCode->Put( (char)0x25 );
656 pNativeCode->Put( value );
657 }
658 else{
659 //16ビット演算の命令プリフィックス
660 char op_prefix=0;
661
662 //オペコード
663 char opcode=(char)0x81;
664
665 __op_format(op_prefix,opcode,0,0,reg,value,MOD_REG);
666 }
667}
668
669void CodeGenerator::op_and_RR( int reg1, int reg2 )
670{
671 //16ビット演算の命令プリフィックス
672 char op_prefix=0;
673
674 //オペコード
675 char opcode=(char)0x23;
676
677 __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG);
678}
679
680void CodeGenerator::op_or_RR( int op_size, int reg1, int reg2 ){
681 //16ビット演算のプリフィックス
682 if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 );
683
684 //オペコード
685 if(op_size==sizeof(char)) pNativeCode->Put( (char)0x0A );
686 else pNativeCode->Put( (char)0x0B );
687
688 //レジスタ
689 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) );
690}
691
692void CodeGenerator::op_xor_RR( int reg1, int reg2 ){
693 // xor reg1, reg2
694
695 if( reg2 == REG_NON )
696 {
697 reg2 = reg1;
698 }
699
700 //16ビット演算の命令プリフィックス
701 char op_prefix=0;
702
703 //オペコード
704 char opcode=(char)0x33;
705
706 __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG);
707}
708
709
710
711void CodeGenerator::op_neg( int reg ){
712 //neg reg
713
714 //命令プリフィックス
715 char op_prefix = (char)0xF7;
716
717 //オペコード
718 char opcode = (char)0xD8;
719
720 __op_format( op_prefix, opcode, reg );
721}
722
723
724
725///////////////////////
726// 64ビット関連
727///////////////////////
728
729void CodeGenerator::op_cdq(){
730 //cdq
731 pNativeCode->Put( (char)0x99 );
732}
733
734
735
736/////////////////////
737// ストリング関係
738/////////////////////
739
740void CodeGenerator::op_rep_movs(int op_size){
741 if(op_size==sizeof(BYTE)){
742 //rep movs byte ptr[edi],byte ptr[esi]
743 pNativeCode->Put( (char)0xF3 );
744 pNativeCode->Put( (char)0xA4 );
745 }
746 else if(op_size==sizeof(short)){
747 //rep movs word ptr[edi],word ptr[esi]
748 pNativeCode->Put( (char)0xF3 );
749 pNativeCode->Put( (char)0x66 );
750 pNativeCode->Put( (char)0xA5 );
751 }
752 else if(op_size==sizeof(long)){
753 //rep movs dword ptr[edi],dword ptr[esi]
754 pNativeCode->Put( (char)0xF3 );
755 pNativeCode->Put( (char)0xA5 );
756 }
757}
758
759
760
761
762//////////////////////////
763// スタック関連
764//////////////////////////
765
766void CodeGenerator::op_push(int reg){
767 //push reg
768
769 if( reg == REG_NON ){
770 op_sub_esp( PTR_SIZE );
771 return;
772 }
773
774 //オペコード、レジスタ
775 __op_format(0,(char)0x50,reg);
776}
777void CodeGenerator::op_push_V(long data, Schedule::Type scheduleType ){
778 //スタックにリテラル値をプッシュ
779 if(-128<=data&&data<=127 && scheduleType == Schedule::None ){
780 //push 8ビット値
781 pNativeCode->Put( (char)0x6A );
782 pNativeCode->Put( (char)data );
783 }
784 else{
785 //push 32ビット値
786 pNativeCode->Put( (char)0x68 );
787 this->PutWithSchedule( data, scheduleType );
788 }
789}
790void CodeGenerator::op_push_M( int base_reg )
791{
792 if( base_reg == REG_EBP )
793 {
794 op_push_M( base_reg, 0 );
795 }
796 else
797 {
798 // push dword ptr[base_reg]
799 __op_format( (char)0xFF, (char)0x30, base_reg );
800 }
801}
802const PertialSchedule *CodeGenerator::op_push_M( int base_reg, long offset, Schedule::Type scheduleType, bool isPertialSchedule )
803{
804 const PertialSchedule *pPertialSchedule = NULL;
805 if( base_reg == REG_NON )
806 {
807 // push dword ptr[offset]
808 pPertialSchedule = __op_format( 0, (char)0xFF, 0, /*opcode->*/0x06, 0, offset, MOD_DISP32, scheduleType, isPertialSchedule );
809 }
810 else
811 {
812 // push dword ptr[base_reg+offset]
813 pPertialSchedule = __op_format( 0, (char)0xFF, 0, /*opcode->*/0x06, base_reg, offset, MOD_BASE_DISP32, scheduleType, isPertialSchedule );
814 }
815 return pPertialSchedule;
816}
817void CodeGenerator::op_pop(int reg){
818 //pop reg
819
820 if( reg == REG_NON ){
821 op_add_esp( PTR_SIZE );
822 return;
823 }
824
825 //オペコード、レジスタ
826 __op_format(0,(char)0x58,reg);
827}
828void CodeGenerator::op_add_esp(long num){
829 //スタックポインタの加算(pop方向)
830
831 //add esp,num
832 if(0xFFFFFF80&num){
833 pNativeCode->Put( (char)0x81 );
834 pNativeCode->Put( (char)0xC4 );
835 pNativeCode->Put( num );
836 }
837 else{
838 //「128 > num > -127」の場合
839 pNativeCode->Put( (char)0x83 );
840 pNativeCode->Put( (char)0xC4 );
841 pNativeCode->Put( (char)num );
842 }
843}
844const PertialSchedule *CodeGenerator::op_sub_esp( long num, bool isPertialSchedule ){
845 //スタックポインタの減算(push方向)
846 const PertialSchedule *pPertialSchedule = NULL;
847
848 //sub esp,num
849 if( (0xFFFFFF80&num) != 0 || isPertialSchedule ){
850 pNativeCode->Put( (char)0x81 );
851 pNativeCode->Put( (char)0xEC );
852
853 if( isPertialSchedule )
854 {
855 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
856 pPertialSchedule = pertialSchedules.back();
857 }
858 pNativeCode->Put( num );
859 }
860 else{
861 //「128 > num > -127」の場合
862 pNativeCode->Put( (char)0x83 );
863 pNativeCode->Put( (char)0xEC );
864 pNativeCode->Put( (char)num );
865 }
866
867 return pPertialSchedule;
868}
869
870
871
872/////////////////////
873// cmp関連
874/////////////////////
875void CodeGenerator::op_cmp_RR( int reg1, int reg2 ){
876 //cmp reg1,reg2
877 __op_format( (char)0, (char)0x3B, 0, reg1, reg2, 0, MOD_REG );
878}
879void CodeGenerator::op_cmp_value(int op_size,int reg,char byte_data){
880 //cmp reg,byte_data
881
882 if(op_size==sizeof(char)&&reg==REG_EAX){
883 //alレジスタの場合は特殊
884 pNativeCode->Put( (char)0x3C );
885
886 //8ビット値
887 pNativeCode->Put( byte_data );
888
889 return;
890 }
891
892 //16ビット演算のプリフィックス
893 if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 );
894
895 //オペコード
896 if(op_size==sizeof(char)) pNativeCode->Put( (char)0x80 );
897 else pNativeCode->Put( (char)0x83 );
898
899 //レジスタ
900 pNativeCode->Put( (char)(0xF8| REGISTER_OPERAND(reg)) );
901
902 //8ビット値
903 pNativeCode->Put( byte_data );
904}
905void CodeGenerator::op_setne( int reg ){
906 //オペコード
907 pNativeCode->Put( (char)0x0F );
908 pNativeCode->Put( (char)0x95 );
909
910 //レジスタ
911 pNativeCode->Put( (char)( 0xC0 | REGISTER_OPERAND(reg) ) );
912}
913
914
915
916////////////////////
917// test関連
918////////////////////
919
920void CodeGenerator::op_test(int reg1,int reg2){
921 //test reg1,reg2
922
923 //1000 0101 11rr rbbb
924 pNativeCode->Put( (char)0x85 );
925 pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) );
926}
927void CodeGenerator::op_test_ah( char cValue )
928{
929 pNativeCode->Put( (char)0xF6 );
930 pNativeCode->Put( (char)0xC4 );
931 pNativeCode->Put( cValue );
932}
933
934
935
936//////////////////////////////
937// 浮動小数点関連
938//////////////////////////////
939
940void CodeGenerator::op_fld_ptr_esp(int type){
941 //スタックポインタが示すバッファのデータを浮動小数点レジスタへロード
942
943 if(type==DEF_DOUBLE){
944 //fld qword ptr[esp]
945 pNativeCode->Put( (char)0xDD );
946 pNativeCode->Put( (char)0x04 );
947 pNativeCode->Put( (char)0x24 );
948 }
949 else if(type==DEF_SINGLE){
950 //fld dword ptr[esp]
951 pNativeCode->Put( (char)0xD9 );
952 pNativeCode->Put( (char)0x04 );
953 pNativeCode->Put( (char)0x24 );
954 }
955 else if(type==DEF_INT64){
956 //fild qword ptr[esp]
957 pNativeCode->Put( (char)0xDF );
958 pNativeCode->Put( (char)0x2C );
959 pNativeCode->Put( (char)0x24 );
960 }
961 else if(type==DEF_LONG){
962 //fild dword ptr[esp]
963 pNativeCode->Put( (char)0xDB );
964 pNativeCode->Put( (char)0x04 );
965 pNativeCode->Put( (char)0x24 );
966 }
967}
968void CodeGenerator::op_fld_basereg(int type,int base_reg){
969 //fld ptr[reg]
970
971 //オペコード
972 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
973 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
974 else compiler.errorMessenger.Output(300,NULL,cp);
975
976 if(base_reg==REG_ESP){
977 pNativeCode->Put( (char)0x04 );
978 pNativeCode->Put( (char)0x24 );
979 }
980 else if(base_reg==REG_EBP){
981 pNativeCode->Put( (char)0x45 );
982 pNativeCode->Put( (char)0x00 );
983 }
984 else{
985 pNativeCode->Put( (char)REGISTER_OPERAND(base_reg) );
986 }
987}
988const PertialSchedule *CodeGenerator::op_fld_base_offset(int type,int base_reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){
989 //fld ptr[reg+offset]
990 const PertialSchedule *pPertialSchedule = NULL;
991
992 //オペコード
993 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
994 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
995 else compiler.errorMessenger.Output(300,NULL,cp);
996
997 //オペコード、レジスタ
998 if(base_reg==REG_ESP){
999 pNativeCode->Put( (char)0x84 );
1000 pNativeCode->Put( (char)0x24 );
1001 }
1002 else{
1003 pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) );
1004 }
1005
1006 //オフセット値
1007 if( isPertialSchedule )
1008 {
1009 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
1010 pPertialSchedule = pertialSchedules.back();
1011 }
1012 this->PutWithSchedule( offset, scheduleType );
1013
1014 return pPertialSchedule;
1015}
1016const PertialSchedule *CodeGenerator::op_fld_base_offset_ex(int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){
1017 //fld ptr[base_reg1+base_reg2+offset]
1018 const PertialSchedule *pPertialSchedule = NULL;
1019
1020 if(base_reg1==REG_ESP){
1021 //SIBバイトのindex部にespは指定できない
1022 base_reg1=base_reg2;
1023 base_reg2=REG_ESP;
1024 }
1025
1026 //オペコード
1027 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
1028 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
1029 else compiler.errorMessenger.Output(300,NULL,cp);
1030
1031 int reg=0;
1032 if(bUseOffset){
1033 ///////////////////////////
1034 // オフセット値を使う
1035 ///////////////////////////
1036
1037 //レジスタ
1038 pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) );
1039
1040 //ベースレジスタ
1041 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
1042
1043 //オフセット値
1044 if( isPertialSchedule )
1045 {
1046 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
1047 pPertialSchedule = pertialSchedules.back();
1048 }
1049 this->PutWithSchedule( offset, scheduleType );
1050 }
1051 else{
1052 ///////////////////////////
1053 // オフセット値を使わない
1054 ///////////////////////////
1055
1056 //レジスタ
1057 pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) );
1058
1059 //ベースレジスタ
1060 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
1061 }
1062
1063 return pPertialSchedule;
1064}
1065void CodeGenerator::op_fstp_basereg(int type,int base_reg){
1066 //fstp ptr[reg]
1067
1068 //オペコード
1069 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
1070 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
1071 else compiler.errorMessenger.Output(300,NULL,cp);
1072
1073 if(base_reg==REG_ESP){
1074 pNativeCode->Put( (char)0x1C );
1075 pNativeCode->Put( (char)0x24 );
1076 }
1077 else if(base_reg==REG_EBP){
1078 pNativeCode->Put( (char)0x5D );
1079 pNativeCode->Put( (char)0x00 );
1080 }
1081 else{
1082 pNativeCode->Put( (char)(0x18|REGISTER_OPERAND(base_reg)) );
1083 }
1084}
1085const PertialSchedule *CodeGenerator::op_fstp_base_offset(int type,int base_reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){
1086 //fstp ptr[reg+offset]
1087 const PertialSchedule *pPertialSchedule = NULL;
1088
1089 //オペコード
1090 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
1091 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
1092 else compiler.errorMessenger.Output(300,NULL,cp);
1093
1094 //オペコード、レジスタ
1095 if(base_reg==REG_ESP){
1096 pNativeCode->Put( (char)0x9C );
1097 pNativeCode->Put( (char)0x24 );
1098 }
1099 else{
1100 pNativeCode->Put( (char)(0x98|REGISTER_OPERAND(base_reg)) );
1101 }
1102
1103 //オフセット値
1104 if( isPertialSchedule )
1105 {
1106 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
1107 pPertialSchedule = pertialSchedules.back();
1108 }
1109 this->PutWithSchedule( offset, scheduleType );
1110
1111 return pPertialSchedule;
1112}
1113const PertialSchedule *CodeGenerator::op_fstp_base_offset_ex(int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){
1114 //fstp ptr[base_reg1+base_reg2+offset]
1115 const PertialSchedule *pPertialSchedule = NULL;
1116
1117 if(base_reg1==REG_ESP){
1118 //SIBバイトのindex部にespは指定できない
1119 base_reg1=base_reg2;
1120 base_reg2=REG_ESP;
1121 }
1122
1123 //オペコード
1124 if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD );
1125 else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 );
1126 else compiler.errorMessenger.Output(300,NULL,cp);
1127
1128 int reg=0;
1129 if(bUseOffset){
1130 ///////////////////////////
1131 // オフセット値を使う
1132 ///////////////////////////
1133
1134 //レジスタ
1135 pNativeCode->Put( (char)(0x9C| REGISTER_OPERAND(reg)<<3) );
1136
1137 //ベースレジスタ
1138 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
1139
1140 //オフセット値
1141 if( isPertialSchedule )
1142 {
1143 pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) );
1144 pPertialSchedule = pertialSchedules.back();
1145 }
1146 this->PutWithSchedule( offset, scheduleType );
1147 }
1148 else{
1149 ///////////////////////////
1150 // オフセット値を使わない
1151 ///////////////////////////
1152
1153 //レジスタ
1154 pNativeCode->Put( (char)(0x1C| REGISTER_OPERAND(reg)<<3) );
1155
1156 //ベースレジスタ
1157 pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) );
1158 }
1159
1160 return pPertialSchedule;
1161}
1162void CodeGenerator::op_fistp_ptr_esp( int typeSize ){
1163 if( typeSize == sizeof(_int64) ){
1164 //64bit
1165
1166 //fistp qword ptr[esp]
1167 fpu_cast();
1168 pNativeCode->Put( (char)0xDF );
1169 pNativeCode->Put( (char)0x3C );
1170 pNativeCode->Put( (char)0x24 );
1171 fpu_cast_end();
1172 }
1173 else if( typeSize == sizeof(long) ){
1174 //32bit
1175
1176 //fistp dword ptr[esp]
1177 fpu_cast();
1178 pNativeCode->Put( (char)0xDB );
1179 pNativeCode->Put( (char)0x1C );
1180 pNativeCode->Put( (char)0x24 );
1181 fpu_cast_end();
1182 }
1183 else{
1184 compiler.errorMessenger.OutputFatalError();
1185 }
1186}
1187void CodeGenerator::op_fstp_push( Type &type ){
1188 //sub esp,size
1189 op_sub_esp( type.GetBasicSize() );
1190
1191 op_fstp_basereg( type.GetBasicType(), REG_ESP );
1192}
1193void CodeGenerator::op_fcompp(){
1194 // fcompp
1195 pNativeCode->Put( (char)0xDE );
1196 pNativeCode->Put( (char)0xD9 );
1197}
1198void CodeGenerator::op_fnstsw_ax()
1199{
1200 // fnstsw ax
1201 pNativeCode->Put( (char)0xDF );
1202 pNativeCode->Put( (char)0xE0 );
1203}
1204
1205
1206
1207//////////////////////////////
1208// レジスタ関連
1209//////////////////////////////
1210
1211void CodeGenerator::op_zero_reg(int reg){
1212 //レジスタに0をセット
1213
1214 op_xor_RR( reg );
1215}
1216
1217void CodeGenerator::fpu_cast(){
1218 ///////////////////////
1219 // FPUの切り捨て設定
1220 ///////////////////////
1221
1222 //sub esp,16
1223 op_sub_esp(16);
1224
1225 //mov dword ptr[esp+4],eax
1226 pNativeCode->Put( (char)0x89 );
1227 pNativeCode->Put( (char)0x44 );
1228 pNativeCode->Put( (char)0x24 );
1229 pNativeCode->Put( (char)0x04 );
1230
1231 //fnstcw word ptr[esp]
1232 pNativeCode->Put( (char)0xD9 );
1233 pNativeCode->Put( (char)0x3C );
1234 pNativeCode->Put( (char)0x24 );
1235
1236 //mov ax,word ptr[esp]
1237 pNativeCode->Put( (char)0x66 );
1238 pNativeCode->Put( (char)0x8B );
1239 pNativeCode->Put( (char)0x04 );
1240 pNativeCode->Put( (char)0x24 );
1241
1242 //or ah,0Ch
1243 pNativeCode->Put( (char)0x80 );
1244 pNativeCode->Put( (char)0xCC );
1245 pNativeCode->Put( (char)0x0C );
1246
1247 //mov word ptr[esp+2],ax
1248 pNativeCode->Put( (char)0x66 );
1249 pNativeCode->Put( (char)0x89 );
1250 pNativeCode->Put( (char)0x44 );
1251 pNativeCode->Put( (char)0x24 );
1252 pNativeCode->Put( (char)0x02 );
1253
1254 //fldcw word ptr[esp+2]
1255 pNativeCode->Put( (char)0xD9 );
1256 pNativeCode->Put( (char)0x6C );
1257 pNativeCode->Put( (char)0x24 );
1258 pNativeCode->Put( (char)0x02 );
1259
1260 //mov eax,dword ptr[esp+4]
1261 pNativeCode->Put( (char)0x8B );
1262 pNativeCode->Put( (char)0x44 );
1263 pNativeCode->Put( (char)0x24 );
1264 pNativeCode->Put( (char)0x04 );
1265
1266 //add esp,16
1267 op_add_esp(16);
1268}
1269void CodeGenerator::fpu_cast_end(){
1270 //sub esp,16
1271 op_sub_esp(16);
1272
1273 //fldcw word ptr[esp]
1274 pNativeCode->Put( (char)0xD9 );
1275 pNativeCode->Put( (char)0x2C );
1276 pNativeCode->Put( (char)0x24 );
1277
1278 //add esp,16
1279 op_add_esp(16);
1280}
1281
1282
1283/////////////////////////////
1284// 関数呼び出し
1285/////////////////////////////
1286
1287void CodeGenerator::op_call_R( int reg )
1288{
1289 // call reg
1290 pNativeCode->Put( (char)0xFF );
1291 pNativeCode->Put( (char)(0xD0|REGISTER_OPERAND(reg)) );
1292}
1293void CodeGenerator::op_call(const UserProc *pUserProc){
1294 pNativeCode->Put( (char)0xE8 );
1295 pNativeCode->PutUserProcSchedule( pUserProc, true );
1296}
1297void CodeGenerator::op_call( const DllProc *pDllProc )
1298{
1299 pNativeCode->Put( (char)0xFF );
1300 pNativeCode->Put( (char)0x15 );
1301 pNativeCode->PutDllProcSchedule( pDllProc );
1302}
1303void CodeGenerator::op_ret(){
1304 pNativeCode->Put( (char)0xC3 );
1305}
1306void CodeGenerator::op_ret( short stackFrameSize )
1307{
1308 pNativeCode->Put( (char)0xC2 );
1309 pNativeCode->Put( stackFrameSize );
1310}
1311void CodeGenerator::op_addressof( int reg, const UserProc *pUserProc )
1312{
1313 //mov reg,userProcAddress
1314
1315 //オペコード、レジスタ
1316 pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) );
1317
1318 //DISP32
1319 pNativeCode->PutUserProcSchedule( pUserProc, false );
1320}
1321void CodeGenerator::op_mov_RV_com_vtbl( int reg, const CClass *pClass )
1322{
1323 // mov reg,vtblAddress
1324
1325 //オペコード、レジスタ
1326 pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) );
1327
1328 //DISP32
1329 pNativeCode->PutComVtblSchedule( pClass );
1330}
1331void CodeGenerator::op_mov_RV_vtbl( int reg, const CClass *pClass )
1332{
1333 // mov reg,vtblAddress
1334
1335 //オペコード、レジスタ
1336 pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) );
1337
1338 //DISP32
1339 pNativeCode->PutVtblSchedule( pClass );
1340}
Note: See TracBrowser for help on using the repository browser.