summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen/x86/Lower.h
blob: 630ccb98dd3599fa28bb876289e7794c514838fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/*! \file lower.h
    \brief A header file to define interface between lowering and register allocator
*/

#ifndef _DALVIK_LOWER
#define _DALVIK_LOWER

#define CODE_CACHE_PADDING 1024 //code space for a single bytecode
// comment out for phase 1 porting
#define PREDICTED_CHAINING
#define JIT_CHAIN

#define NUM_DEPENDENCIES 24 /* max number of dependencies from a LowOp */
//compilaton flags used by NCG O1
#define DUMP_EXCEPTION //to measure performance, required to have correct exception handling
/*! multiple versions for hardcoded registers */
#define HARDREG_OPT
#define CFG_OPT
/*! remove redundant move ops when accessing virtual registers */
#define MOVE_OPT
/*! remove redundant spill of virtual registers */
#define SPILL_OPT
#define XFER_OPT
//#define DSE_OPT //no perf improvement for cme
/*! use live range analysis to allocate registers */
#define LIVERANGE_OPT
/*! remove redundant null check */
#define NULLCHECK_OPT
//#define BOUNDCHECK_OPT
/*! optimize the access to glue structure */
#define GLUE_OPT
#define CALL_FIX
#define NATIVE_FIX
#define INVOKE_FIX //optimization
#define GETVR_FIX //optimization

#include "Dalvik.h"
#include "enc_wrapper.h"
#include "AnalysisO1.h"
#include "compiler/CompilerIR.h"

//compilation flags for debugging
//#define DEBUG_INFO
//#define DEBUG_CALL_STACK
//#define DEBUG_IGET_OBJ
//#define DEBUG_NCG_CODE_SIZE
//#define DEBUG_NCG
//#define DEBUG_NCG_1
//#define DEBUG_LOADING
//#define USE_INTERPRETER
//#define DEBUG_EACH_BYTECODE

/*! registers for functions are hardcoded */
#define HARDCODE_REG_CALL
#define HARDCODE_REG_SHARE
#define HARDCODE_REG_HELPER

#define PhysicalReg_FP PhysicalReg_EDI
#define PhysicalReg_Glue PhysicalReg_EBP

//COPIED from interp/InterpDefs.h
#define FETCH(_offset) (rPC[(_offset)])
#define INST_INST(_inst) ((_inst) & 0xff)
#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
#define INST_B(_inst)       ((_inst) >> 12)
#define INST_AA(_inst)      ((_inst) >> 8)

//#include "vm/mterp/common/asm-constants.h"
#define offEBP_self 8
#define offEBP_spill -56
#define offThread_exception 68
#define offClassObject_descriptor 24
#define offArrayObject_length 8
#ifdef PROFILE_FIELD_ACCESS
#define offStaticField_value 24
#define offInstField_byteOffset 24
#else
#define offStaticField_value 16
#define offInstField_byteOffset 16
#endif

#ifdef EASY_GDB
#define offStackSaveArea_prevFrame 4
#define offStackSaveArea_savedPc 8
#define offStackSaveArea_method 12
#define offStackSaveArea_localRefTop 16 // -> StackSaveArea.xtra.locakRefCookie
#define offStackSaveArea_returnAddr 20
#define offStackSaveArea_isDebugInterpreted 24
#define sizeofStackSaveArea 24
#else
#define offStackSaveArea_prevFrame 0
#define offStackSaveArea_savedPc 4
#define offStackSaveArea_method 8
#define offStackSaveArea_localRefTop 12 // -> StackSaveArea.xtra.locakRefCookie
#define offStackSaveArea_returnAddr 16
#define offStackSaveArea_isDebugInterpreted 20
#define sizeofStackSaveArea 20
#endif

#define offClassObject_status 44
#define offClassObject_accessFlags 32
#ifdef MTERP_NO_UNALIGN_64
#define offArrayObject_contents 16
#else
#define offArrayObject_contents 12
#endif

#define offField_clazz 0
#define offObject_clazz 0
#define offClassObject_vtable 116
#define offClassObject_pDvmDex 40
#define offClassObject_super 72
#define offClassObject_vtableCount 112
#define offMethod_name 16
#define offMethod_accessFlags 4
#define offMethod_methodIndex 8
#define offMethod_registersSize 10
#define offMethod_outsSize 12
#define offGlue_interpStackEnd 32
#define offThread_inJitCodeCache 124
#define offThread_jniLocal_nextEntry 168
#define offMethod_insns 32
#ifdef ENABLE_TRACING
#define offMethod_insns_bytecode 44
#define offMethod_insns_ncg 48
#endif

#define offGlue_pc     0
#define offGlue_fp     4
#define offGlue_retval 8

#define offThread_curFrame 4
#define offGlue_method 16
#define offGlue_methodClassDex 20
#define offGlue_self 24
#define offGlue_pSelfSuspendCount 36
#define offGlue_cardTable 40
#define offGlue_pDebuggerActive 44
#define offGlue_pActiveProfilers 48
#define offGlue_entryPoint 52
#define offGlue_icRechainCount 84
#define offGlue_espEntry 88
#define offGlue_spillRegion 92
#define offDvmDex_pResStrings 8
#define offDvmDex_pResClasses 12
#define offDvmDex_pResMethods 16
#define offDvmDex_pResFields  20
#define offMethod_clazz       0

// Definitions must be consistent with vm/mterp/x86/header.S
#define FRAME_SIZE     124

typedef enum ArgsDoneType {
    ArgsDone_Normal = 0,
    ArgsDone_Native,
    ArgsDone_Full
} ArgsDoneType;

/*! An enum type
    to list bytecodes for AGET, APUT
*/
typedef enum ArrayAccess {
    AGET, AGET_WIDE, AGET_CHAR, AGET_SHORT, AGET_BOOLEAN, AGET_BYTE,
    APUT, APUT_WIDE, APUT_CHAR, APUT_SHORT, APUT_BOOLEAN, APUT_BYTE
} ArrayAccess;
/*! An enum type
    to list bytecodes for IGET, IPUT
*/
typedef enum InstanceAccess {
    IGET, IGET_WIDE, IPUT, IPUT_WIDE
} InstanceAccess;
/*! An enum type
    to list bytecodes for SGET, SPUT
*/
typedef enum StaticAccess {
    SGET, SGET_WIDE, SPUT, SPUT_WIDE
} StaticAccess;

typedef enum JmpCall_type {
    JmpCall_uncond = 1,
    JmpCall_cond,
    JmpCall_reg, //jump reg32
    JmpCall_call
} JmpCall_type;

////////////////////////////////////////////////////////////////
/* data structure for native codes */
/* Due to space considation, a lowered op (LowOp) has two operands (LowOpnd), depending on
   the type of the operand, LowOpndReg or LowOpndImm or LowOpndMem will follow */
/*! type of an operand can be immediate, register or memory */
typedef enum LowOpndType {
  LowOpndType_Imm = 0,
  LowOpndType_Reg,
  LowOpndType_Mem,
  LowOpndType_Label,
  LowOpndType_NCG,
  LowOpndType_Chain
} LowOpndType;
typedef enum LowOpndDefUse {
  LowOpndDefUse_Def = 0,
  LowOpndDefUse_Use,
  LowOpndDefUse_UseDef
} LowOpndDefUse;

/*!
\brief base data structure for an operand */
typedef struct LowOpnd {
  LowOpndType type;
  OpndSize size;
  LowOpndDefUse defuse;
} LowOpnd;
/*!
\brief data structure for a register operand */
typedef struct LowOpndReg {
  LowOpndRegType regType;
  int logicalReg;
  int physicalReg;
} LowOpndReg;
/*!
\brief data structure for an immediate operand */
typedef struct LowOpndImm {
  union {
    s4 value;
    unsigned char bytes[4];
  };
} LowOpndImm;

typedef struct LowOpndNCG {
  union {
    s4 value;
    unsigned char bytes[4];
  };
} LowOpndNCG;

#define LABEL_SIZE 256
typedef struct LowOpndLabel {
  char label[LABEL_SIZE];
  bool isLocal;
} LowOpndLabel;

/* get ready for optimizations at LIR
   add MemoryAccessType & virtualRegNum to memory operands */
typedef enum MemoryAccessType {
  MemoryAccess_GLUE,
  MemoryAccess_VR,
  MemoryAccess_SPILL,
  MemoryAccess_Unknown
} MemoryAccessType;
typedef enum UseDefEntryType {
  UseDefType_Ctrl = 0,
  UseDefType_Float,
  UseDefType_MemVR,
  UseDefType_MemSpill,
  UseDefType_MemUnknown,
  UseDefType_Reg
} UseDefEntryType;
typedef struct UseDefProducerEntry {
  UseDefEntryType type;
  int index; //enum PhysicalReg for "Reg" type
  int producerSlot;
} UseDefProducerEntry;
#define MAX_USE_PER_ENTRY 50 /* at most 10 uses for each entry */
typedef struct UseDefUserEntry {
  UseDefEntryType type;
  int index;
  int useSlots[MAX_USE_PER_ENTRY];
  int num_uses_per_entry;
} UseDefUserEntry;

/*!
\brief data structure for a memory operand */
typedef struct LowOpndMem {
  LowOpndImm m_disp;
  LowOpndImm m_scale;
  LowOpndReg m_index;
  LowOpndReg m_base;
  bool hasScale;
  MemoryAccessType mType;
  int index;
} LowOpndMem;

typedef enum AtomOpCode {
    ATOM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH = -15,
    ATOM_NORMAL_ALU = -14,
    ATOM_PSEUDO_ENTRY_BLOCK = -13,
    ATOM_PSEUDO_EXIT_BLOCK = -12,
    ATOM_PSEUDO_TARGET_LABEL = -11,
    ATOM_PSEUDO_CHAINING_CELL_HOT = -10,
    ATOM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED = -9,
    ATOM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON = -8,
    ATOM_PSEUDO_CHAINING_CELL_NORMAL = -7,
    ATOM_PSEUDO_DALVIK_BYTECODE_BOUNDARY = -6,
    ATOM_PSEUDO_ALIGN4 = -5,
    ATOM_PSEUDO_PC_RECONSTRUCTION_CELL = -4,
    ATOM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL = -3,
    ATOM_PSEUDO_EH_BLOCK_LABEL = -2,
    ATOM_PSEUDO_NORMAL_BLOCK_LABEL = -1,
    ATOM_NORMAL,
} AtomOpCode;

typedef enum DependencyType {
  Dependency_RAW,
  Dependency_WAW,
  Dependency_WAR,
  Dependency_FLAG
} DependencyType;
typedef struct DependencyStruct {
  DependencyType dType;
  int nodeId;
  int latency;
} DependencyStruct;

typedef struct LowOpBlock {
  LIR generic;
  Mnemonic opCode;
  AtomOpCode opCode2;
} LowOpBlock;

/*!
\brief data structure for a lowered operation */
typedef struct LowOp {
  LIR generic;
  Mnemonic opCode;
  AtomOpCode opCode2;
  LowOpnd opnd1;
  LowOpnd opnd2;
  int numOperands;
} LowOp;

typedef struct LowOpLabel {
  LowOp lop;
  LowOpndLabel labelOpnd;
}LowOpLabel;

typedef struct LowOpNCG {
  LowOp lop;
  LowOpndNCG ncgOpnd;
}LowOpNCG;

typedef struct LowOpBlockLabel {
  LowOpBlock lop;
  LowOpndImm immOpnd;
} LowOpBlockLabel;

typedef struct LowOpImm {
  LowOp lop;
  LowOpndImm immOpnd;
} LowOpImm;

typedef struct LowOpMem {
  LowOp lop;
  LowOpndMem memOpnd;
} LowOpMem;

typedef struct LowOpReg {
  LowOp lop;
  LowOpndReg regOpnd;
} LowOpReg;

typedef struct LowOpImmImm {
  LowOp lop;
  LowOpndImm immOpnd1;
  LowOpndImm immOpnd2;
} LowOpImmImm;

typedef struct LowOpImmReg {
  LowOp lop;
  LowOpndImm immOpnd1;
  LowOpndReg regOpnd2;
} LowOpImmReg;

typedef struct LowOpImmMem {
  LowOp lop;
  LowOpndImm immOpnd1;
  LowOpndMem memOpnd2;
} LowOpImmMem;

typedef struct LowOpRegImm {
  LowOp lop;
  LowOpndReg regOpnd1;
  LowOpndImm immOpnd2;
} LowOpRegImm;

typedef struct LowOpRegReg {
  LowOp lop;
  LowOpndReg regOpnd1;
  LowOpndReg regOpnd2;
} LowOpRegReg;

typedef struct LowOpRegMem {
  LowOp lop;
  LowOpndReg regOpnd1;
  LowOpndMem memOpnd2;
} LowOpRegMem;

typedef struct LowOpMemImm {
  LowOp lop;
  LowOpndMem memOpnd1;
  LowOpndImm immOpnd2;
} LowOpMemImm;

typedef struct LowOpMemReg {
  LowOp lop;
  LowOpndMem memOpnd1;
  LowOpndReg regOpnd2;
} LowOpMemReg;

typedef struct LowOpMemMem {
  LowOp lop;
  LowOpndMem memOpnd1;
  LowOpndMem memOpnd2;
} LowOpMemMem;

/*!
\brief data structure for labels used when lowering a method

four label maps are defined: globalMap globalShortMap globalWorklist globalShortWorklist
globalMap: global labels where codePtr points to the label
           freeLabelMap called in clearNCG
globalWorklist: global labels where codePtr points to an instruciton using the label
  standalone NCG -------
                accessed by insertLabelWorklist & performLabelWorklist
  code cache ------
                inserted by performLabelWorklist(false),
                handled & cleared by generateRelocation in NcgFile.c
globalShortMap: local labels where codePtr points to the label
                freeShortMap called after generation of one bytecode
globalShortWorklist: local labels where codePtr points to an instruction using the label
                accessed by insertShortWorklist & insertLabel
definition of local label: life time of the label is within a bytecode or within a helper function
extra label maps are used by code cache:
  globalDataWorklist VMAPIWorklist
*/
typedef struct LabelMap {
  char label[LABEL_SIZE];
  char* codePtr; //code corresponding to the label or code that uses the label
  struct LabelMap* nextItem;
  OpndSize size;
  uint  addend;
} LabelMap;
/*!
\brief data structure to handle forward jump (GOTO, IF)

accessed by insertNCGWorklist & performNCGWorklist
*/
typedef struct NCGWorklist {
  //when WITH_JIT, relativePC stores the target basic block id
  s4 relativePC; //relative offset in bytecode
  int offsetPC;  //PC in bytecode
  int offsetNCG; //PC in native code
  char* codePtr; //code for native jump instruction
  struct NCGWorklist* nextItem;
  OpndSize size;
}NCGWorklist;
/*!
\brief data structure to handle SWITCH & FILL_ARRAY_DATA

two data worklist are defined: globalDataWorklist (used by code cache) & methodDataWorklist
methodDataWorklist is accessed by insertDataWorklist & performDataWorklist
*/
typedef struct DataWorklist {
  s4 relativePC; //relative offset in bytecode to access the data
  int offsetPC;  //PC in bytecode
  int offsetNCG; //PC in native code
  char* codePtr; //code for native instruction add_imm_reg imm, %edx
  char* codePtr2;//code for native instruction add_reg_reg %eax, %edx for SWITCH
                 //                            add_imm_reg imm, %edx for FILL_ARRAY_DATA
  struct DataWorklist* nextItem;
}DataWorklist;
#ifdef ENABLE_TRACING
typedef struct MapWorklist {
  u4 offsetPC;
  u4 offsetNCG;
  int isStartOfPC; //1 --> true 0 --> false
  struct MapWorklist* nextItem;
} MapWorklist;
#endif

#define BUFFER_SIZE 1024 //# of Low Ops buffered
//the following three numbers are hardcoded, please CHECK
#define BYTECODE_SIZE_PER_METHOD 81920
#define NATIVE_SIZE_PER_DEX 19000000 //FIXME for core.jar: 16M --> 18M for O1
#define NATIVE_SIZE_FOR_VM_STUBS 100000
#define MAX_HANDLER_OFFSET 1024 //maximal number of handler offsets

extern int LstrClassCastExceptionPtr, LstrInstantiationErrorPtr, LstrInternalError, LstrFilledNewArrayNotImpl;
extern int LstrArithmeticException, LstrArrayIndexException, LstrArrayStoreException, LstrStringIndexOutOfBoundsException;
extern int LstrDivideByZero, LstrNegativeArraySizeException, LstrNoSuchMethodError, LstrNullPointerException;
extern int LdoubNeg, LvaluePosInfLong, LvalueNegInfLong, LvalueNanLong, LshiftMask, Lvalue64, L64bits, LintMax, LintMin;

extern LabelMap* globalMap;
extern LabelMap* globalShortMap;
extern LabelMap* globalWorklist;
extern LabelMap* globalShortWorklist;
extern NCGWorklist* globalNCGWorklist;
extern DataWorklist* methodDataWorklist;
#ifdef ENABLE_TRACING
extern MapWorklist* methodMapWorklist;
#endif
extern PhysicalReg scratchRegs[4];

#define C_SCRATCH_1 scratchRegs[0]
#define C_SCRATCH_2 scratchRegs[1]
#define C_SCRATCH_3 scratchRegs[2] //scratch reg inside callee

extern LowOp* ops[BUFFER_SIZE];
extern bool isScratchPhysical;
extern u2* rPC;
extern u2 inst;
extern int offsetPC;
extern int offsetNCG;
extern int mapFromBCtoNCG[BYTECODE_SIZE_PER_METHOD];
extern char* streamStart;

extern char* streamCode;

extern char* streamMethodStart; //start of the method
extern char* stream; //current stream pointer
extern char* streamMisPred;
extern int lowOpTimeStamp;
extern Method* currentMethod;
extern int currentExceptionBlockIdx;

extern int globalMapNum;
extern int globalWorklistNum;
extern int globalDataWorklistNum;
extern int globalPCWorklistNum;
extern int chainingWorklistNum;
extern int VMAPIWorklistNum;

extern LabelMap* globalDataWorklist;
extern LabelMap* globalPCWorklist;
extern LabelMap* chainingWorklist;
extern LabelMap* VMAPIWorklist;

extern int ncgClassNum;
extern int ncgMethodNum;

extern LowOp* lirTable[200]; //Number of LIRs for all bytecodes do not exceed 200
extern int num_lirs_in_table;

bool existATryBlock(Method* method, int startPC, int endPC);
// interface between register allocator & lowering
extern int num_removed_nullCheck;

int registerAlloc(int type, int reg, bool isPhysical, bool updateRef);
int registerAllocMove(int reg, int type, bool isPhysical, int srcReg);
int checkVirtualReg(int reg, LowOpndRegType type, int updateRef); //returns the physical register
int updateRefCount(int reg, LowOpndRegType type);
int updateRefCount2(int reg, int type, bool isPhysical);
int spillVirtualReg(int vrNum, LowOpndRegType type, bool updateTable);
int isVirtualRegConstant(int regNum, LowOpndRegType type, int* valuePtr, bool updateRef);
int checkTempReg(int reg, int type, bool isPhysical, int vA);
bool checkTempReg2(int reg, int type, bool isPhysical, int physicalRegForVR);
int freeReg(bool spillGL);
int nextVersionOfHardReg(PhysicalReg pReg, int refCount);
int updateVirtualReg(int reg, LowOpndRegType type);
void setVRNullCheck(int regNum, OpndSize size);
bool isVRNullCheck(int regNum, OpndSize size);
void setVRBoundCheck(int vr_array, int vr_index);
bool isVRBoundCheck(int vr_array, int vr_index);
int requestVRFreeDelay(int regNum, u4 reason);
void cancelVRFreeDelayRequest(int regNum, u4 reason);
bool getVRFreeDelayRequested(int regNum);
bool isGlueHandled(int glue_reg);
void resetGlue(int glue_reg);
void updateGlue(int reg, bool isPhysical, int glue_reg);
int updateVRAtUse(int reg, LowOpndRegType pType, int regAll);
int touchEcx();
int touchEax();
int touchEdx();
int beforeCall(const char* target);
int afterCall(const char* target);
void startBranch();
void endBranch();
void rememberState(int);
void goToState(int);
void transferToState(int);
void globalVREndOfBB(const Method*);
void constVREndOfBB();
void startNativeCode(int num, int type);
void endNativeCode();
void donotSpillReg(int physicalReg);
void doSpillReg(int physicalReg);

#define XMM_1 PhysicalReg_XMM0
#define XMM_2 PhysicalReg_XMM1
#define XMM_3 PhysicalReg_XMM2
#define XMM_4 PhysicalReg_XMM3

/////////////////////////////////////////////////////////////////////////////////
//LR[reg] = disp + PR[base_reg] or disp + LR[base_reg]
void load_effective_addr(int disp, int base_reg, bool isBasePhysical,
                          int reg, bool isPhysical);
void load_effective_addr_scale(int base_reg, bool isBasePhysical,
                                int index_reg, bool isIndexPhysical, int scale,
                                int reg, bool isPhysical);
void load_fpu_cw(int disp, int base_reg, bool isBasePhysical);
void store_fpu_cw(bool checkException, int disp, int base_reg, bool isBasePhysical);
void convert_integer(OpndSize srcSize, OpndSize dstSize);
void load_fp_stack(LowOp* op, OpndSize size, int disp, int base_reg, bool isBasePhysical);
void load_int_fp_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical);
void load_int_fp_stack_imm(OpndSize size, int imm);
void store_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical);
void store_int_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical);

void load_fp_stack_VR(OpndSize size, int vA);
void load_int_fp_stack_VR(OpndSize size, int vA);
void store_fp_stack_VR(bool pop, OpndSize size, int vA);
void store_int_fp_stack_VR(bool pop, OpndSize size, int vA);
void compare_VR_ss_reg(int vA, int reg, bool isPhysical);
void compare_VR_sd_reg(int vA, int reg, bool isPhysical);
void fpu_VR(ALU_Opcode opc, OpndSize size, int vA);
void compare_reg_mem(LowOp* op, OpndSize size, int reg, bool isPhysical,
                           int disp, int base_reg, bool isBasePhysical);
void compare_mem_reg(OpndSize size,
                           int disp, int base_reg, bool isBasePhysical,
                           int reg, bool isPhysical);
void compare_VR_reg(OpndSize size,
                           int vA,
                           int reg, bool isPhysical);
void compare_imm_reg(OpndSize size, int imm,
                           int reg, bool isPhysical);
void compare_imm_mem(OpndSize size, int imm,
                           int disp, int base_reg, bool isBasePhysical);
void compare_imm_VR(OpndSize size, int imm,
                           int vA);
void compare_reg_reg(int reg1, bool isPhysical1,
                           int reg2, bool isPhysical2);
void compare_reg_reg_16(int reg1, bool isPhysical1,
                         int reg2, bool isPhysical2);
void compare_ss_mem_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
                              int reg, bool isPhysical);
void compare_ss_reg_with_reg(LowOp* op, int reg1, bool isPhysical1,
                              int reg2, bool isPhysical2);
void compare_sd_mem_with_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
                              int reg, bool isPhysical);
void compare_sd_reg_with_reg(LowOp* op, int reg1, bool isPhysical1,
                              int reg2, bool isPhysical2);
void compare_fp_stack(bool pop, int reg, bool isDouble);
void test_imm_reg(OpndSize size, int imm, int reg, bool isPhysical);
void test_imm_mem(OpndSize size, int imm, int disp, int reg, bool isPhysical);

void conditional_move_reg_to_reg(OpndSize size, ConditionCode cc, int reg1, bool isPhysical1, int reg, bool isPhysical);
void move_ss_mem_to_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
                        int reg, bool isPhysical);
void move_ss_reg_to_mem(LowOp* op, int reg, bool isPhysical,
                         int disp, int base_reg, bool isBasePhysical);
LowOpRegMem* move_ss_mem_to_reg_noalloc(int disp, int base_reg, bool isBasePhysical,
                         MemoryAccessType mType, int mIndex,
                         int reg, bool isPhysical);
LowOpMemReg* move_ss_reg_to_mem_noalloc(int reg, bool isPhysical,
                         int disp, int base_reg, bool isBasePhysical,
                         MemoryAccessType mType, int mIndex);
void move_sd_mem_to_reg(int disp, int base_reg, bool isBasePhysical,
                         int reg, bool isPhysical);
void move_sd_reg_to_mem(LowOp* op, int reg, bool isPhysical,
                         int disp, int base_reg, bool isBasePhysical);

void conditional_jump(ConditionCode cc, const char* target, bool isShortTerm);
void unconditional_jump(const char* target, bool isShortTerm);
void conditional_jump_int(ConditionCode cc, int target, OpndSize size);
void unconditional_jump_int(int target, OpndSize size);
void unconditional_jump_reg(int reg, bool isPhysical);
void call(const char* target);
void call_reg(int reg, bool isPhysical);
void call_reg_noalloc(int reg, bool isPhysical);
void call_mem(int disp, int reg, bool isPhysical);
void x86_return();

void alu_unary_reg(OpndSize size, ALU_Opcode opc, int reg, bool isPhysical);
void alu_unary_mem(LowOp* op, OpndSize size, ALU_Opcode opc, int disp, int base_reg, bool isBasePhysical);

void alu_binary_imm_mem(OpndSize size, ALU_Opcode opc,
                         int imm, int disp, int base_reg, bool isBasePhysical);
void alu_binary_imm_reg(OpndSize size, ALU_Opcode opc, int imm, int reg, bool isPhysical);
void alu_binary_mem_reg(OpndSize size, ALU_Opcode opc,
                         int disp, int base_reg, bool isBasePhysical,
                         int reg, bool isPhysical);
void alu_binary_VR_reg(OpndSize size, ALU_Opcode opc, int vA, int reg, bool isPhysical);
void alu_sd_binary_VR_reg(ALU_Opcode opc, int vA, int reg, bool isPhysical, bool isSD);
void alu_binary_reg_reg(OpndSize size, ALU_Opcode opc,
                         int reg1, bool isPhysical1,
                         int reg2, bool isPhysical2);
void alu_binary_reg_mem(OpndSize size, ALU_Opcode opc,
                         int reg, bool isPhysical,
                         int disp, int base_reg, bool isBasePhysical);

void fpu_mem(LowOp* op, ALU_Opcode opc, OpndSize size, int disp, int base_reg, bool isBasePhysical);
void alu_ss_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical,
                            int reg2, bool isPhysical2);
void alu_sd_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical,
                            int reg2, bool isPhysical2);

void push_mem_to_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical);
void push_reg_to_stack(OpndSize size, int reg, bool isPhysical);

//returns the pointer to end of the native code
void move_reg_to_mem(OpndSize size,
                      int reg, bool isPhysical,
                      int disp, int base_reg, bool isBasePhysical);
LowOpRegMem* move_mem_to_reg(OpndSize size,
                      int disp, int base_reg, bool isBasePhysical,
                      int reg, bool isPhysical);
void movez_mem_to_reg(OpndSize size,
                      int disp, int base_reg, bool isBasePhysical,
                      int reg, bool isPhysical);
void movez_reg_to_reg(OpndSize size,
                      int reg, bool isPhysical,
                      int reg2, bool isPhysical2);
void moves_mem_to_reg(LowOp* op, OpndSize size,
                      int disp, int base_reg, bool isBasePhysical,
                      int reg, bool isPhysical);
void movez_mem_disp_scale_to_reg(OpndSize size,
                      int base_reg, bool isBasePhysical,
                      int disp, int index_reg, bool isIndexPhysical, int scale,
                      int reg, bool isPhysical);
void moves_mem_disp_scale_to_reg(OpndSize size,
                      int base_reg, bool isBasePhysical,
                      int disp, int index_reg, bool isIndexPhysical, int scale,
                      int reg, bool isPhysical);
void move_reg_to_reg(OpndSize size,
                      int reg, bool isPhysical,
                      int reg2, bool isPhysical2);
void move_reg_to_reg_noalloc(OpndSize size,
                      int reg, bool isPhysical,
                      int reg2, bool isPhysical2);
void move_mem_scale_to_reg(OpndSize size,
                            int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale,
                            int reg, bool isPhysical);
void move_mem_disp_scale_to_reg(OpndSize size,
                int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
                int reg, bool isPhysical);
void move_reg_to_mem_scale(OpndSize size,
                            int reg, bool isPhysical,
                            int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale);
void move_reg_to_mem_disp_scale(OpndSize size,
                            int reg, bool isPhysical,
                            int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale);
void move_imm_to_mem(OpndSize size, int imm,
                      int disp, int base_reg, bool isBasePhysical);
void set_VR_to_imm(u2 vA, OpndSize size, int imm);
void set_VR_to_imm_noalloc(u2 vA, OpndSize size, int imm);
void set_VR_to_imm_noupdateref(LowOp* op, u2 vA, OpndSize size, int imm);
void move_imm_to_reg(OpndSize size, int imm, int reg, bool isPhysical);
void move_imm_to_reg_noalloc(OpndSize size, int imm, int reg, bool isPhysical);

//LR[reg] = VR[vB]
//or
//PR[reg] = VR[vB]
void get_virtual_reg(u2 vB, OpndSize size, int reg, bool isPhysical);
void get_virtual_reg_noalloc(u2 vB, OpndSize size, int reg, bool isPhysical);
//VR[v] = LR[reg]
//or
//VR[v] = PR[reg]
void set_virtual_reg(u2 vA, OpndSize size, int reg, bool isPhysical);
void set_virtual_reg_noalloc(u2 vA, OpndSize size, int reg, bool isPhysical);
void get_VR_ss(int vB, int reg, bool isPhysical);
void set_VR_ss(int vA, int reg, bool isPhysical);
void get_VR_sd(int vB, int reg, bool isPhysical);
void set_VR_sd(int vA, int reg, bool isPhysical);

int spill_reg(int reg, bool isPhysical);
int unspill_reg(int reg, bool isPhysical);

void move_reg_to_mem_noalloc(OpndSize size,
                      int reg, bool isPhysical,
                      int disp, int base_reg, bool isBasePhysical,
                      MemoryAccessType mType, int mIndex);
LowOpRegMem* move_mem_to_reg_noalloc(OpndSize size,
                      int disp, int base_reg, bool isBasePhysical,
                      MemoryAccessType mType, int mIndex,
                      int reg, bool isPhysical);

//////////////////////////////////////////////////////////////
int insertLabel(const char* label, bool checkDup);
int export_pc();
int simpleNullCheck(int reg, bool isPhysical, int vr);
int nullCheck(int reg, bool isPhysical, int exceptionNum, int vr);
int handlePotentialException(
                             ConditionCode code_excep, ConditionCode code_okay,
                             int exceptionNum, const char* errName);
int get_currentpc(int reg, bool isPhysical);
int get_self_pointer(int reg, bool isPhysical);
int get_res_strings(int reg, bool isPhysical);
int get_res_classes(int reg, bool isPhysical);
int get_res_fields(int reg, bool isPhysical);
int get_res_methods(int reg, bool isPhysical);
int get_glue_method_class(int reg, bool isPhysical);
int get_glue_method(int reg, bool isPhysical);
int set_glue_method(int reg, bool isPhysical);
int get_glue_dvmdex(int reg, bool isPhysical);
int set_glue_dvmdex(int reg, bool isPhysical);
int get_suspendCount(int reg, bool isPhysical);
int get_return_value(OpndSize size, int reg, bool isPhysical);
int set_return_value(OpndSize size, int reg, bool isPhysical);
int clear_exception();
int get_exception(int reg, bool isPhysical);
int set_exception(int reg, bool isPhysical);
int save_pc_fp_to_glue();
int savearea_from_fp(int reg, bool isPhysical);

int call_moddi3();
int call_divdi3();
int call_fmod();
int call_fmodf();
int call_dvmFindCatchBlock();
int call_dvmThrowVerificationError();
int call_dvmAllocObject();
int call_dvmAllocArrayByClass();
int call_dvmResolveMethod();
int call_dvmResolveClass();
int call_dvmInstanceofNonTrivial();
int call_dvmThrow();
int call_dvmThrowWithMessage();
int call_dvmCheckSuspendPending();
int call_dvmLockObject();
int call_dvmUnlockObject();
int call_dvmInitClass();
int call_dvmAllocPrimitiveArray();
int call_dvmInterpHandleFillArrayData();
int call_dvmNcgHandlePackedSwitch();
int call_dvmNcgHandleSparseSwitch();
int call_dvmJitHandlePackedSwitch();
int call_dvmJitHandleSparseSwitch();
int call_dvmJitToInterpTraceSelectNoChain();
int call_dvmJitToPatchPredictedChain();
int call_dvmJitToInterpNormal();
int call_dvmJitToInterpTraceSelect();
int call_dvmQuasiAtomicSwap64();
int call_dvmQuasiAtomicRead64();
int call_dvmCanPutArrayElement();
int call_dvmFindInterfaceMethodInCache();
int call_dvmHandleStackOverflow();
int call_dvmResolveString();
int call_dvmResolveInstField();
int call_dvmResolveStaticField();

//labels and branches
//shared branch to resolve class: 2 specialized versions
//OPTION 1: call & ret
//OPTION 2: store jump back label in a fixed register or memory
//jump to .class_resolve, then jump back
//OPTION 3: share translator code
/* global variables: ncg_rPC */
int resolve_class(
                  int startLR/*logical register index*/, bool isPhysical, int tmp/*const pool index*/,
                  int thirdArg);
/* EXPORT_PC; movl exceptionPtr, -8(%esp); movl descriptor, -4(%esp); lea; call; lea; jmp */
int throw_exception_message(int exceptionPtr, int obj_reg, bool isPhysical,
                            int startLR/*logical register index*/, bool startPhysical);
/* EXPORT_PC; movl exceptionPtr, -8(%esp); movl imm, -4(%esp); lea; call; lea; jmp */
int throw_exception(int exceptionPtr, int imm,
                    int startLR/*logical register index*/, bool startPhysical);

void freeShortMap();
int insertDataWorklist(s4 relativePC, char* codePtr1);
#ifdef ENABLE_TRACING
int insertMapWorklist(s4 BCOffset, s4 NCGOffset, int isStartOfPC);
#endif
int performNCGWorklist();
int performDataWorklist();
void performLabelWorklist();
void performMethodLabelWorklist();
void freeLabelMap();
void performSharedWorklist();
void performChainingWorklist();
void freeNCGWorklist();
void freeDataWorklist();
void freeLabelWorklist();
void freeChainingWorklist();

int common_invokeArgsDone(ArgsDoneType form, bool isJitFull);
int common_backwardBranch();
int common_exceptionThrown();
int common_errNullObject();
int common_errArrayIndex();
int common_errArrayStore();
int common_errNegArraySize();
int common_errNoSuchMethod();
int common_errDivideByZero();
int common_periodicChecks_entry();
int common_periodicChecks4();
int common_gotoBail();
int common_gotoBail_0();
int common_StringIndexOutOfBounds();
void goto_invokeArgsDone();

//lower a bytecode
int lowerByteCode(const Method* method);

int op_nop();
int op_move();
int op_move_from16();
int op_move_16();
int op_move_wide();
int op_move_wide_from16();
int op_move_wide_16();
int op_move_result();
int op_move_result_wide();
int op_move_exception();

int op_return_void();
int op_return();
int op_return_wide();
int op_const_4();
int op_const_16();
int op_const();
int op_const_high16();
int op_const_wide_16();
int op_const_wide_32();
int op_const_wide();
int op_const_wide_high16();
int op_const_string();
int op_const_string_jumbo();
int op_const_class();
int op_monitor_enter();
int op_monitor_exit();
int op_check_cast();
int op_instance_of();

int op_array_length();
int op_new_instance();
int op_new_array();
int op_filled_new_array();
int op_filled_new_array_range();
int op_fill_array_data();
int op_throw();
int op_throw_verification_error();
int op_goto();
int op_goto_16();
int op_goto_32();
int op_packed_switch();
int op_sparse_switch();
int op_if_ge();
int op_aget();
int op_aget_wide();
int op_aget_object();
int op_aget_boolean();
int op_aget_byte();
int op_aget_char();
int op_aget_short();
int op_aput();
int op_aput_wide();
int op_aput_object();
int op_aput_boolean();
int op_aput_byte();
int op_aput_char();
int op_aput_short();
int op_iget();
int op_iget_wide(bool isVolatile);
int op_iget_object();
int op_iget_boolean();
int op_iget_byte();
int op_iget_char();
int op_iget_short();
int op_iput();
int op_iput_wide(bool isVolatile);
int op_iput_object();
int op_iput_boolean();
int op_iput_byte();
int op_iput_char();
int op_iput_short();
int op_sget();
int op_sget_wide(bool isVolatile);
int op_sget_object();
int op_sget_boolean();
int op_sget_byte();
int op_sget_char();
int op_sget_short();
int op_sput(bool isObj);
int op_sput_wide(bool isVolatile);
int op_sput_object();
int op_sput_boolean();
int op_sput_byte();
int op_sput_char();
int op_sput_short();
int op_invoke_virtual();
int op_invoke_super();
int op_invoke_direct();
int op_invoke_static();
int op_invoke_interface();
int op_invoke_virtual_range();
int op_invoke_super_range();
int op_invoke_direct_range();
int op_invoke_static_range();
int op_invoke_interface_range();
int op_int_to_long();
int op_add_long_2addr();
int op_add_int_lit8();
int op_cmpl_float();
int op_cmpg_float();
int op_cmpl_double();
int op_cmpg_double();
int op_cmp_long();
int op_if_eq();
int op_if_ne();
int op_if_lt();
int op_if_gt();
int op_if_le();
int op_if_eqz();
int op_if_nez();
int op_if_ltz();
int op_if_gez();
int op_if_gtz();
int op_if_lez();
int op_neg_int();
int op_not_int();
int op_neg_long();
int op_not_long();
int op_neg_float();
int op_neg_double();
int op_int_to_float();
int op_int_to_double();
int op_long_to_int();
int op_long_to_float();
int op_long_to_double();
int op_float_to_int();
int op_float_to_long();
int op_float_to_double();
int op_double_to_int();
int op_double_to_long();
int op_double_to_float();
int op_int_to_byte();
int op_int_to_char();
int op_int_to_short();
int op_add_int();
int op_sub_int();
int op_mul_int();
int op_div_int();
int op_rem_int();
int op_and_int();
int op_or_int();
int op_xor_int();
int op_shl_int();
int op_shr_int();
int op_ushr_int();
int op_add_long();
int op_sub_long();
int op_mul_long();
int op_div_long();
int op_rem_long();
int op_and_long();
int op_or_long();
int op_xor_long();
int op_shl_long();
int op_shr_long();
int op_ushr_long();
int op_add_float();
int op_sub_float();
int op_mul_float();
int op_div_float();
int op_rem_float();
int op_add_double();
int op_sub_double();
int op_mul_double();
int op_div_double();
int op_rem_double();
int op_add_int_2addr();
int op_sub_int_2addr();
int op_mul_int_2addr();
int op_div_int_2addr();
int op_rem_int_2addr();
int op_and_int_2addr();
int op_or_int_2addr();
int op_xor_int_2addr();
int op_shl_int_2addr();
int op_shr_int_2addr();
int op_ushr_int_2addr();
int op_sub_long_2addr();
int op_mul_long_2addr();
int op_div_long_2addr();
int op_rem_long_2addr();
int op_and_long_2addr();
int op_or_long_2addr();
int op_xor_long_2addr();
int op_shl_long_2addr();
int op_shr_long_2addr();
int op_ushr_long_2addr();
int op_add_float_2addr();
int op_sub_float_2addr();
int op_mul_float_2addr();
int op_div_float_2addr();
int op_rem_float_2addr();
int op_add_double_2addr();
int op_sub_double_2addr();
int op_mul_double_2addr();
int op_div_double_2addr();
int op_rem_double_2addr();
int op_add_int_lit16();
int op_rsub_int();
int op_mul_int_lit16();
int op_div_int_lit16();
int op_rem_int_lit16();
int op_and_int_lit16();
int op_or_int_lit16();
int op_xor_int_lit16();
int op_rsub_int_lit8();
int op_mul_int_lit8();
int op_div_int_lit8();
int op_rem_int_lit8();
int op_and_int_lit8();
int op_or_int_lit8();
int op_xor_int_lit8();
int op_shl_int_lit8();
int op_shr_int_lit8();
int op_ushr_int_lit8();
int op_execute_inline(bool isRange);
int op_invoke_object_init_range();
int op_iget_quick();
int op_iget_wide_quick();
int op_iget_object_quick();
int op_iput_quick();
int op_iput_wide_quick();
int op_iput_object_quick();
int op_invoke_virtual_quick();
int op_invoke_virtual_quick_range();
int op_invoke_super_quick();
int op_invoke_super_quick_range();

///////////////////////////////////////////////
void set_reg_opnd(LowOpndReg* op_reg, int reg, bool isPhysical, LowOpndRegType type);
void set_mem_opnd(LowOpndMem* mem, int disp, int base, bool isPhysical);
void set_mem_opnd_scale(LowOpndMem* mem, int base, bool isPhysical, int disp, int index, bool indexPhysical, int scale);
LowOpImm* dump_imm(Mnemonic m, OpndSize size,
               int imm);
LowOpNCG* dump_ncg(Mnemonic m, OpndSize size, int imm);
LowOpImm* dump_imm_with_codeaddr(Mnemonic m, OpndSize size,
               int imm, char* codePtr);
LowOpImm* dump_special(AtomOpCode cc, int imm);
LowOpMem* dump_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
               int disp, int base_reg, bool isBasePhysical);
LowOpReg* dump_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
               int reg, bool isPhysical, LowOpndRegType type);
LowOpReg* dump_reg_noalloc(Mnemonic m, OpndSize size,
               int reg, bool isPhysical, LowOpndRegType type);
LowOpMemImm* dump_imm_mem_noalloc(Mnemonic m, OpndSize size,
                           int imm,
                           int disp, int base_reg, bool isBasePhysical,
                           MemoryAccessType mType, int mIndex);
LowOpRegReg* dump_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
                   int reg, bool isPhysical,
                   int reg2, bool isPhysical2, LowOpndRegType type);
LowOpRegReg* dump_movez_reg_reg(Mnemonic m, OpndSize size,
                        int reg, bool isPhysical,
                        int reg2, bool isPhysical2);
LowOpRegMem* dump_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
                   int disp, int base_reg, bool isBasePhysical,
                   MemoryAccessType mType, int mIndex,
                   int reg, bool isPhysical, LowOpndRegType type);
LowOpRegMem* dump_mem_reg_noalloc(Mnemonic m, OpndSize size,
                           int disp, int base_reg, bool isBasePhysical,
                           MemoryAccessType mType, int mIndex,
                           int reg, bool isPhysical, LowOpndRegType type);
LowOpRegMem* dump_mem_scale_reg(Mnemonic m, OpndSize size,
                         int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
                         int reg, bool isPhysical, LowOpndRegType type);
LowOpMemReg* dump_reg_mem_scale(Mnemonic m, OpndSize size,
                         int reg, bool isPhysical,
                         int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
                         LowOpndRegType type);
LowOpMemReg* dump_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
                   int reg, bool isPhysical,
                   int disp, int base_reg, bool isBasePhysical,
                   MemoryAccessType mType, int mIndex, LowOpndRegType type);
LowOpMemReg* dump_reg_mem_noalloc(Mnemonic m, OpndSize size,
                           int reg, bool isPhysical,
                           int disp, int base_reg, bool isBasePhysical,
                           MemoryAccessType mType, int mIndex, LowOpndRegType type);
LowOpRegImm* dump_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
                   int imm, int reg, bool isPhysical, LowOpndRegType type, bool chaining);
LowOpMemImm* dump_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
                   int imm,
                   int disp, int base_reg, bool isBasePhysical,
                   MemoryAccessType mType, int mIndex, bool chaining);
LowOpMemReg* dump_fp_mem(Mnemonic m, OpndSize size, int reg,
                  int disp, int base_reg, bool isBasePhysical,
                  MemoryAccessType mType, int mIndex);
LowOpRegMem* dump_mem_fp(Mnemonic m, OpndSize size,
                  int disp, int base_reg, bool isBasePhysical,
                  MemoryAccessType mType, int mIndex,
                  int reg);
LowOpLabel* dump_label(Mnemonic m, OpndSize size, int imm,
               const char* label, bool isLocal);

unsigned getJmpCallInstSize(OpndSize size, JmpCall_type type);
bool lowerByteCodeJit(const Method* method, const u2* codePtr, MIR* mir);
void startOfBasicBlock(struct BasicBlock* bb);
extern LowOpBlockLabel* traceLabelList;
extern struct BasicBlock* traceCurrentBB;
extern struct MIR* traceCurrentMIR;
void startOfTrace(const Method* method, LowOpBlockLabel* labelList, int, CompilationUnit*);
void endOfTrace(bool freeOnly);
LowOp* jumpToBasicBlock(char* instAddr, int targetId);
LowOp* condJumpToBasicBlock(char* instAddr, ConditionCode cc, int targetId);
bool jumpToException(const char* target);
int codeGenBasicBlockJit(const Method* method, BasicBlock* bb);
void endOfBasicBlock(struct BasicBlock* bb);
void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir);
int insertChainingWorklist(int bbId, char * codeStart);
void startOfTraceO1(const Method* method, LowOpBlockLabel* labelList, int exceptionBlockId, CompilationUnit *cUnit);
void endOfTraceO1();
int isPowerOfTwo(int imm);
void move_chain_to_mem(OpndSize size, int imm,
                        int disp, int base_reg, bool isBasePhysical);
void move_chain_to_reg(OpndSize size, int imm, int reg, bool isPhysical);

void dumpImmToMem(int vrNum, OpndSize size, int value);
bool isInMemory(int regNum, OpndSize size);
int touchEbx();
int boundCheck(int vr_array, int reg_array, bool isPhysical_array,
               int vr_index, int reg_index, bool isPhysical_index,
               int exceptionNum);
int getRelativeOffset(const char* target, bool isShortTerm, JmpCall_type type, bool* unknown,
                      OpndSize* immSize);
int getRelativeNCG(s4 tmp, JmpCall_type type, bool* unknown, OpndSize* size);
void freeAtomMem();
OpndSize estOpndSizeFromImm(int target);

void preprocessingBB(BasicBlock* bb);
void preprocessingTrace();
void dump_nop(int size);
#endif