hschumann2/TempleOS-Source-Code
0838
1 2Bool PrsAsmImm(CCmpCtrl *cc,CAsmArg *arg)3{4 if (arg->imm_or_off_present)5 LexExcept(cc,"Already one immediate at ");6 arg->imm_or_off_present=TRUE;7 arg->num.local_asm_undef_hash=NULL;8 arg->num.glbl_asm_undef_hash=NULL;9 cc->asm_undef_hash=NULL;10 cc->abs_cnts=0;11 cc->flags&=~(CCF_UNRESOLVED+CCF_LOCAL);12 if (!IsLexExpression2Bin(cc,&arg->num.machine_code))13 LexSkipEol(cc);14 else {15 if (cc->abs_cnts.externs)16 LexExcept(cc,"Extern Not Allowed at ");17 if (cc->flags & CCF_UNRESOLVED) {18 if (cc->flags & CCF_LOCAL) {19 arg->num.local_asm_undef_hash=cc->asm_undef_hash;20 cc->asm_undef_hash=NULL;21 } else {22 arg->num.glbl_asm_undef_hash=cc->asm_undef_hash;23 cc->asm_undef_hash=NULL;24 }25 } else {26 arg->num.i=Call(arg->num.machine_code);27 arg->num.glbl_asm_undef_hash=cc->asm_undef_hash;28 cc->asm_undef_hash=NULL;29 Free(arg->num.machine_code);30 arg->num.machine_code=NULL;31 }32 }33 return TRUE;34}35 36U0 PrsAsmArg(CCmpCtrl *cc,CAsmArg *arg,Bool rel)37{38 CHashGeneric *tmph,*tmph1;39 CHashReg *tmpr;40 MemSet(arg,0,sizeof(CAsmArg));41 arg->seg =REG_NONE;42 arg->reg1=REG_NONE;43 arg->reg2=REG_NONE;44 arg->scale=1;45 while (TRUE) {46 if (cc->token==TK_IDENT) {47 if (tmph=cc->hash_entry) {48 if (tmph->type&HTG_TYPE_MASK==HTT_REG) {49 tmpr=tmph;50 arg->reg1_type=tmpr->reg_type;51 switch (tmpr->reg_type) {52 start:53 case REGT_R8:54 arg->size=1;55 break;56 case REGT_R16:57 arg->size=2;58 break;59 case REGT_R32:60 arg->size=4;61 break;62 case REGT_R64:63 arg->size=8;64 break;65 end:66 arg->reg1=tmpr->reg_num;67 Lex(cc);68 return;69 case REGT_SEG:70 arg->seg=tmpr->reg_num;71 if (Lex(cc)!=':') {72 arg->just_seg=TRUE;73 return;74 } else75 Lex(cc); //skip ":"76 break;77 case REGT_FSTK:78 case REGT_MM:79 case REGT_XMM:80 arg->size=8;81 arg->reg1=tmpr->reg_num;82 Lex(cc);83 return;84 }85 } else {86 if ((tmph->type&HTG_TYPE_MASK==HTT_CLASS||87 tmph->type&HTG_TYPE_MASK==HTT_INTERNAL_TYPE) &&88 (tmph1=HashFind(cc->cur_str,cmp.asm_hash,HTT_ASM_KEYWORD)))89 tmph=tmph1;90 if (tmph->type&HTG_TYPE_MASK==HTT_ASM_KEYWORD) {91 switch (tmph->user_data0) {92 case AKW_I8:93 case AKW_U8:94 arg->size=1;95 break;96 case AKW_I16:97 case AKW_U16:98 arg->size=2;99 break;100 case AKW_I32:101 case AKW_U32:102 arg->size=4;103 break;104 case AKW_I64:105 case AKW_U64:106 arg->size=8;107 break;108 default:109 LexExcept(cc,"syntax error at ");110 }111 Lex(cc); //skip keyword112 } else113 goto pa_asm_direct_imm;114 }115 } else {116pa_asm_direct_imm:117 PrsAsmImm(cc,arg);118 arg->num.abs_cnts=cc->abs_cnts;119 if (arg->size<=1 && !rel && arg->num.abs_cnts&1) {120 if (cc->aotc->seg_size==16)121 arg->size=2;122 else123 arg->size=4;124 }125 if (cc->token!='[')126 return;127 }128 } else if (cc->token=='[') {129 arg->indirect=TRUE;130 Lex(cc); // skip [131 while (cc->token && cc->token!=']') {132 if (cc->token==TK_IDENT) {133 if (tmph=cc->hash_entry) {134 if (tmph->type&HTG_TYPE_MASK==HTT_REG &&135 REGT_R16<=tmph(CHashReg *)->reg_type<=REGT_R64) {136 tmpr=tmph;137 arg->reg2_type=tmpr->reg_type;138 if (arg->reg1==REG_NONE) {139 if (tmpr->reg_num&7==REG_RSP) {140 arg->reg1=4;141 arg->reg2=tmpr->reg_num;142 } else143 arg->reg1=tmpr->reg_num;144 } else145 arg->reg2=tmpr->reg_num;146 Lex(cc);147 } else148 goto pa_asm_indirect_imm;149 } else150 goto pa_asm_indirect_imm;151 } else if (cc->token=='*') {152 Lex(cc);153 if (cc->token!=TK_I64)154 LexExcept(cc,"Expecting scale factor at ");155 arg->scale=cc->cur_i64;156 Lex(cc); //skip scale157 if (arg->reg2!=REG_NONE) {158 SwapI64(&arg->reg1,&arg->reg2);159 SwapI64(&arg->reg1_type,&arg->reg2_type);160 }161 } else if (cc->token=='+') {162 Lex(cc); //skip '+'163 } else {164pa_asm_indirect_imm:165 PrsAsmImm(cc,arg);166 arg->num.abs_cnts=cc->abs_cnts;167 }168 }169 if (cc->token!=']')170 LexExcept(cc,"Missing ']' at ");171 Lex(cc); //skip ]172 return;173 } else174 goto pa_asm_direct_imm;175 }176}177 178I64 AsmMakeArgMask(CCmpCtrl *cc,CAsmArg *arg)179{180 CAOTCtrl *aotc=cc->aotc;181 I64 res;182 if (arg->just_seg) {183 switch (arg->seg) {184 case 0: res=1<<ARGT_ES|1<<ARGT_SREG; break;185 case 1: res=1<<ARGT_CS|1<<ARGT_SREG; break;186 case 2: res=1<<ARGT_SS|1<<ARGT_SREG; break;187 case 3: res=1<<ARGT_DS|1<<ARGT_SREG; break;188 case 4: res=1<<ARGT_FS|1<<ARGT_SREG; break;189 case 5: res=1<<ARGT_GS|1<<ARGT_SREG; break;190 }191 goto mm_done;192 }193 if (arg->reg1_type==REGT_FSTK) {194 if (arg->reg1)195 res=1<<ARGT_STI;196 else197 res=1<<ARGT_ST0|1<<ARGT_STI;198 goto mm_done;199 }200 res=cmp.size_arg_mask[arg->size];201 if (aotc->seg_size==64)202 res&=0xFF0FFFFFFF;203 204 if (arg->reg1!=REG_NONE && arg->imm_or_off_present && !arg->num.i &&205 !arg->num.glbl_asm_undef_hash && !arg->num.local_asm_undef_hash)206 arg->imm_or_off_present=FALSE; //Zero displacement207 208 if (arg->reg2!=REG_NONE || arg->scale!=1) {209 res&=0x0000FF0000;210 goto mm_done;211 }212 213 if (arg->indirect) {214 if (arg->imm_or_off_present)215 res&=0x00FFFF0000;216 else217 res&=0x000FFF0000;218 } else {219 if (arg->imm_or_off_present)220 res&=0x000F000FFE;221 else222 res&=0x3F0FFFF000;223 }224 if (arg->seg!=REG_NONE)225 res&=0x00FFFF0000;226 if (arg->reg1==REG_NONE) {227 if (arg->indirect)228 res&=0x00FFFF0000;229 else if (arg->num.i<0) {230 if (arg->num.i>=I8_MIN)231 res&=0x8FE;232 else if (arg->num.i>=I16_MIN)233 res&=0x8EE;234 else if (arg->num.i>=I32_MIN)235 res&=0x8CE;236 else237 res&=0x88E;238 } else {239 if (arg->num.i<=I8_MAX)240 res&=0xFFE;241 else if (arg->num.i<=U8_MAX)242 res&=0xFEE;243 else if (arg->num.i<=I16_MAX)244 res&=0xEEE;245 else if (arg->num.i<=U16_MAX)246 res&=0xECE;247 else if (arg->num.i<=I32_MAX)248 res&=0xCCE;249 else if (arg->num.i<=U32_MAX)250 res&=0xC8E;251 else252 res&=0x88E;253 }254 } else {255 res&= 0x3F00FFF000;256 if (!arg->indirect) //M8-M64257 res&=0xFFFF0FFFFF;258 }259 switch (arg->reg1) {260 case REG_RAX: res&=~0x3000000000; break;261 case REG_RCX: res&=~0x2F00000000; break;262 case REG_RDX: res&=~0x1F00000000; break;263 default: res&=~0x3F00000000;264 }265mm_done:266 return res;267}268 269Bool AsmStoreNum(CCmpCtrl *cc,CAsmNum2 *num2,I64 cnt,Bool U8_avail)270{271 CAOTCtrl *aotc=cc->aotc;272 I64 i;273 CAOTAbsAddr *tmpa;274 275 if (!num2->imm_flag)276 num2->num.i-=num2->rel;277 for (i=0;i<cnt;i++) {278 if (num2->U8_cnt==1) {279 if (num2->num.local_asm_undef_hash||num2->num.glbl_asm_undef_hash)280 AsmUnresolvedAdd(cc,num2->num.machine_code,IET_REL_I8+num2->imm_flag,281 aotc->rip,num2->rel,num2->num.local_asm_undef_hash,282 num2->num.glbl_asm_undef_hash,cc->lex_include_stk->line_num,283 U8_avail);284 else if (!num2->imm_flag && !(I8_MIN<=num2->num.i<=I8_MAX))285 LexExcept(cc,"Branch out of range at ");286 if (num2->imm_flag) {287 if (num2->num.abs_cnts.abs_addres&1) {288 tmpa=CAlloc(sizeof(CAOTAbsAddr));289 tmpa->next=aotc->abss;290 aotc->abss=tmpa;291 tmpa->rip=aotc->rip;292 tmpa->type=AAT_ADD_U8;293 }294 } else {295 if (num2->num.abs_cnts.c_addres&1) {296 tmpa=CAlloc(sizeof(CAOTAbsAddr));297 tmpa->next=aotc->abss;298 aotc->abss=tmpa;299 tmpa->rip=aotc->rip;300 tmpa->type=AAT_SUB_U8;301 }302 }303 AOTStoreCodeU8(cc,num2->num.i);304 } else {305 if (num2->U8_cnt==2) {306 if (num2->num.local_asm_undef_hash||num2->num.glbl_asm_undef_hash)307 AsmUnresolvedAdd(cc,num2->num.machine_code,IET_REL_I16+num2->imm_flag,308 aotc->rip,num2->rel,num2->num.local_asm_undef_hash,309 num2->num.glbl_asm_undef_hash,cc->lex_include_stk->line_num,310 U8_avail);311 else if (!num2->imm_flag && !(I16_MIN<=num2->num.i<=I16_MAX))312 LexExcept(cc,"Branch out of range at ");313 if (num2->imm_flag) {314 if (num2->num.abs_cnts.abs_addres&1) {315 tmpa=CAlloc(sizeof(CAOTAbsAddr));316 tmpa->next=aotc->abss;317 aotc->abss=tmpa;318 tmpa->rip=aotc->rip;319 tmpa->type=AAT_ADD_U16;320 }321 } else {322 if (num2->num.abs_cnts.c_addres&1) {323 tmpa=CAlloc(sizeof(CAOTAbsAddr));324 tmpa->next=aotc->abss;325 aotc->abss=tmpa;326 tmpa->rip=aotc->rip;327 tmpa->type=AAT_SUB_U16;328 }329 }330 AOTStoreCodeU8(cc,num2->num.i.u8[0]);331 AOTStoreCodeU8(cc,num2->num.i.u8[1]);332 } else if (num2->U8_cnt==4) {333 if (num2->num.local_asm_undef_hash||num2->num.glbl_asm_undef_hash)334 AsmUnresolvedAdd(cc,num2->num.machine_code,IET_REL_I32+num2->imm_flag,335 aotc->rip,num2->rel,num2->num.local_asm_undef_hash,336 num2->num.glbl_asm_undef_hash,cc->lex_include_stk->line_num,337 U8_avail);338 else if (!num2->imm_flag && !(I32_MIN<=num2->num.i<=I32_MAX))339 LexExcept(cc,"Branch out of range at ");340 if (num2->imm_flag) {341 if (num2->num.abs_cnts.abs_addres&1) {342 tmpa=CAlloc(sizeof(CAOTAbsAddr));343 tmpa->next=aotc->abss;344 aotc->abss=tmpa;345 tmpa->rip=aotc->rip;346 tmpa->type=AAT_ADD_U32;347 }348 } else {349 if (num2->num.abs_cnts.c_addres&1) {350 tmpa=CAlloc(sizeof(CAOTAbsAddr));351 tmpa->next=aotc->abss;352 aotc->abss=tmpa;353 tmpa->rip=aotc->rip;354 tmpa->type=AAT_SUB_U32;355 }356 }357 AOTStoreCodeU32(cc,num2->num.i);358 } else if (num2->U8_cnt==8) {359 if (num2->num.local_asm_undef_hash||num2->num.glbl_asm_undef_hash)360 AsmUnresolvedAdd(cc,num2->num.machine_code,IET_REL_I64+num2->imm_flag,361 aotc->rip,num2->rel,num2->num.local_asm_undef_hash,362 num2->num.glbl_asm_undef_hash,cc->lex_include_stk->line_num,363 U8_avail);364 if (num2->imm_flag) {365 if (num2->num.abs_cnts.abs_addres&1) {366 tmpa=CAlloc(sizeof(CAOTAbsAddr));367 tmpa->next=aotc->abss;368 aotc->abss=tmpa;369 tmpa->rip=aotc->rip;370 tmpa->type=AAT_ADD_U64;371 }372 } else {373 if (num2->num.abs_cnts.c_addres&1) {374 tmpa=CAlloc(sizeof(CAOTAbsAddr));375 tmpa->next=aotc->abss;376 aotc->abss=tmpa;377 tmpa->rip=aotc->rip;378 tmpa->type=AAT_SUB_U64;379 }380 }381 AOTStoreCodeU64(cc,num2->num.i);382 }383 if (U8_avail && !num2->num.local_asm_undef_hash &&384 !num2->num.glbl_asm_undef_hash &&385 !num2->imm_flag && -124<=num2->num.i<=123) {386 LexWarn(cc,"could use I8 displacement at ");387 return FALSE;388 }389 }390 }391 return TRUE;392}393 394U8 asm_seg_prefixes[6]={0x26,0x2E,0x36,0x3E,0x64,0x65};395 396Bool PrsAsmInst(CCmpCtrl *cc,CHashOpcode *tmpo,I64 argcnt)397{398 CAOTCtrl *aotc=cc->aotc;399 I64 i,j,arg1,arg2,om,seg,arg1mask,arg2mask;400 CAsmArg *tmpa1,*tmpa2;401 Bool ModrM_complete,U8_avail=FALSE,found_second_possible=FALSE;402 CInst *tmpins;403 CAsmIns cur,best;404 405 best.U8_cnt=255;406 if (argcnt>0)407 arg1mask=AsmMakeArgMask(cc,&aotc->arg1);408 else409 arg1mask=1;410 if (argcnt>1)411 arg2mask=AsmMakeArgMask(cc,&aotc->arg2);412 else413 arg2mask=1;414 for (i=0;i<tmpo->inst_entry_cnt;i++) {415 tmpins=&tmpo->ins[i];416 if (tmpins->arg1==ARGT_REL8 || tmpins->arg2==ARGT_REL8)417 U8_avail=TRUE;418 if (Bt(&arg1mask,tmpins->arg1) && Bt(&arg2mask,tmpins->arg2) &&419 (!(tmpins->flags&IEF_NOT_IN_64_BIT) || aotc->seg_size!=64)) {420 MemSet(&cur,0,sizeof(CAsmIns));421 cur.tmpins=tmpins;422 ModrM_complete=FALSE;423 cur.is_dft=ToBool(tmpins->flags & IEF_DFT);424 if (aotc->seg_size==64) {425 if (tmpins->flags & IEF_48_REX)426 cur.REX=0x48;427 else428 cur.REX=0x40;429 }430 cur.disp.imm_flag=TRUE;431 cur.imm.imm_flag=TRUE;432 om=tmpins->opcode_modifier;433 arg1=tmpins->arg1;434 arg2=tmpins->arg2;435 tmpa1=&aotc->arg1;436 tmpa2=&aotc->arg2;437 cur.last_opcode_U8=tmpins->opcode[tmpins->opcode_cnt-1];438 439 if (tmpins->slash_val<8) {440 cur.ModrM|=tmpins->slash_val<<3;441 cur.has_ModrM=TRUE;442 }443 444 if (aotc->seg_size==16 && tmpins->flags & IEF_OP_SIZE32 ||445 aotc->seg_size!=16 && tmpins->flags & IEF_OP_SIZE16)446 cur.has_operand_prefix=TRUE;447 448 if (om==OM_IB) cur.imm.U8_cnt=1;449 else if (om==OM_IW) cur.imm.U8_cnt=2;450 else if (om==OM_ID) cur.imm.U8_cnt=4;451 452 if (om==OM_CB) {453 cur.imm.U8_cnt=1;454 cur.imm.imm_flag=FALSE;455 } else if (om==OM_CW) {456 cur.imm.U8_cnt=2;457 cur.imm.imm_flag=FALSE;458 } else if (om==OM_CD) {459 cur.imm.U8_cnt=4;460 cur.imm.imm_flag=FALSE;461 }462 463 if (argcnt==1) {464 if (best.U8_cnt!=255 && !found_second_possible && !best.is_dft) {465 found_second_possible=TRUE;466 if (!aotc->arg1.size)467 PrintWarn("no size specified at %s,%04d\n",468 cc->lex_include_stk->full_name,469 cc->lex_include_stk->line_num-1);470 }471 if (tmpins->flags & IEF_PLUS_OPCODE) {472 if (tmpins->slash_val==SV_R_REG) {473 cur.last_opcode_U8|=tmpa1->reg1&7;474 if (tmpa1->reg1&15>7)475 cur.REX|=1;476 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?477 cur.has_REX=TRUE;478 } else {//SV_I_REG479 if (tmpa1->reg1_type==REGT_FSTK)480 cur.last_opcode_U8+=tmpa1->reg1;481 }482 }483 if (arg1==ARGT_R64 || arg1==ARGT_RM64 || arg1==ARGT_M64)484 cur.REX|=8;485 if (ARGT_RM8<=arg1<=ARGT_RM64 || ARGT_M8<=arg1<=ARGT_M64) {486 if (aotc->seg_size==16)487 cur.has_addr_prefix=TRUE;488 489 cur.has_ModrM=TRUE;490 if (tmpa1->imm_or_off_present && tmpa1->indirect &&491 tmpa1->reg1==REG_NONE) {492 cur.ModrM=cur.ModrM+5;493 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));494 cur.disp.U8_cnt=4;495 if (aotc->seg_size==64)496 cur.disp.imm_flag=FALSE;497 } else {498 if (tmpa1->reg2==REG_NONE && tmpa1->scale==1) {499 cur.ModrM|=tmpa1->reg1&7;500 if (tmpa1->reg1&15>7)501 cur.REX|=1;502 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?503 cur.has_REX=TRUE;504 } else {505 cur.ModrM|=4;506 cur.has_SIB=TRUE;507 if (tmpa1->scale==1)508 cur.SIB=0;509 else if (tmpa1->scale==2)510 cur.SIB=0x40;511 else if (tmpa1->scale==4)512 cur.SIB=0x80;513 else if (tmpa1->scale==8)514 cur.SIB=0xC0;515 if (tmpa1->reg2==REG_NONE) {516 ModrM_complete=TRUE;517 cur.SIB|=(tmpa1->reg1&7)<<3+REG_RBP;518 if (tmpa1->reg1&15>7)519 cur.REX|=2;520 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?521 cur.has_REX=TRUE;522 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));523 cur.disp.U8_cnt=4;524 } else {525 cur.SIB|=(tmpa1->reg1&7)<<3+tmpa1->reg2&7;526 if (tmpa1->reg1&15>7)527 cur.REX|=2;528 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?529 cur.has_REX=TRUE;530 if (tmpa1->reg2&15>7)531 cur.REX|=1;532 if (tmpa1->reg2>=20) //RBPu8,RSPu8,RSIu8,RDIu8?533 cur.has_REX=TRUE;534 if (tmpa1->reg2&7==REG_RBP &&535 !tmpa1->imm_or_off_present && tmpa1->indirect) {536 cur.ModrM|=0x40;537 cur.disp.U8_cnt=1;538 ModrM_complete=TRUE;539 }540 }541 }542 if (!ModrM_complete) {543 if (tmpa1->imm_or_off_present) {544 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));545 if (!cur.disp.num.machine_code &&546 I8_MIN<=cur.disp.num.i<=I8_MAX) {547 cur.ModrM|=0x40;548 cur.disp.U8_cnt=1;549 } else if (aotc->seg_size==16) {550 cur.ModrM|=0x80;551 cur.disp.U8_cnt=2;552 } else {553 cur.ModrM|=0x80;554 cur.disp.U8_cnt=4;555 }556 } else if (!tmpa1->indirect) {557 cur.has_addr_prefix=FALSE;558 cur.ModrM|=0xC0;559 } else {560 if (tmpa1->reg1&7==REG_RBP) {561 cur.ModrM|=0x40;562 cur.disp.U8_cnt=1;563 }564 }565 }566 }567 } else if (ARGT_REL8<=arg1<=ARGT_REL32 || ARGT_IMM8<=arg1<=ARGT_IMM64 ||568 ARGT_UIMM8<=arg1<=ARGT_UIMM64) {569 if (arg1==ARGT_IMM64 || arg2==ARGT_UIMM64)570 cur.REX|=8;571 MemCpy(&cur.imm.num,&tmpa1->num,sizeof(CAsmNum));572 }573 } else if (argcnt==2) {574 if (best.U8_cnt!=255 && !found_second_possible && !best.is_dft) {575 found_second_possible=TRUE;576 if (!aotc->arg1.size && !aotc->arg2.size)577 PrintWarn("no size specified at %s,%04d\n",578 cc->lex_include_stk->full_name,579 cc->lex_include_stk->line_num-1);580 }581 if (tmpins->flags & IEF_PLUS_OPCODE) {582 if (tmpins->slash_val==SV_R_REG) {583 if (ARGT_AL<=arg1<=ARGT_RAX) {584 cur.last_opcode_U8|=tmpa2->reg1&7;585 if (tmpa2->reg1&15>7)586 cur.REX|=1;587 if (tmpa2->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?588 cur.has_REX=TRUE;589 } else {590 cur.last_opcode_U8|=tmpa1->reg1&7;591 if (tmpa1->reg1&15>7)592 cur.REX|=1;593 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?594 cur.has_REX=TRUE;595 }596 } else {//SV_I_REG597 if (tmpa1->reg1_type==REGT_FSTK)598 cur.last_opcode_U8|=tmpa1->reg1;599 if (tmpa2->reg1_type==REGT_FSTK)600 cur.last_opcode_U8|=tmpa2->reg1;601 }602 }603 if (arg1==ARGT_RM64 || arg2==ARGT_RM64 ||604 arg1==ARGT_M64 || arg2==ARGT_M64 ||605 arg1==ARGT_R64 || arg2==ARGT_R64)606 cur.REX|=8;607 if (ARGT_RM8<=arg1<=ARGT_RM64 || ARGT_RM8<=arg2<=ARGT_RM64 ||608 ARGT_M8<=arg1<=ARGT_M64 || ARGT_M8<=arg2<=ARGT_M64) {609 if (aotc->seg_size==16)610 cur.has_addr_prefix=TRUE;611 cur.has_ModrM=TRUE;612 if (ARGT_RM8<=arg2<=ARGT_RM64 || ARGT_M8<=arg2<=ARGT_M64) {613 tmpa1=&aotc->arg2;614 tmpa2=&aotc->arg1;615 }616 if (tmpins->slash_val==SV_R_REG) {617 if (tmpa2->just_seg)618 cur.ModrM|=tmpa2->seg<<3;619 else {620 if (tmpa2->reg1==REG_NONE) {621 cur.ModrM|=(tmpa1->reg1&7)<<3;622 if (tmpa1->reg1&15>7)623 cur.REX|=4;624 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?625 cur.has_REX=TRUE;626 } else {627 cur.ModrM|=(tmpa2->reg1&7)<<3;628 if (tmpa2->reg1&15>7)629 cur.REX|=4;630 if (tmpa2->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?631 cur.has_REX=TRUE;632 }633 }634 }635 if (tmpa1->reg2==REG_NONE && tmpa1->scale==1) {636 if (tmpa1->reg1!=REG_NONE) {637 cur.ModrM|=tmpa1->reg1&7;638 if (tmpa1->reg1&15>7)639 cur.REX|=1;640 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?641 cur.has_REX=TRUE;642 }643 } else {644 cur.ModrM|=4;645 cur.has_SIB=TRUE;646 if (tmpa1->scale==1)647 cur.SIB=0;648 else if (tmpa1->scale==2)649 cur.SIB=0x40;650 else if (tmpa1->scale==4)651 cur.SIB=0x80;652 else if (tmpa1->scale==8)653 cur.SIB=0xC0;654 if (tmpa1->reg2==REG_NONE) {655 ModrM_complete=TRUE;656 cur.SIB|=(tmpa1->reg1&7)<<3+5;657 if (tmpa1->reg1&15>7)658 cur.REX|=2;659 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?660 cur.has_REX=TRUE;661 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));662 cur.disp.U8_cnt=4;663 } else {664 cur.SIB|=(tmpa1->reg1&7)<<3+tmpa1->reg2&7;665 if (tmpa1->reg1&15>7)666 cur.REX|=2;667 if (tmpa1->reg1>=20) //RBPu8,RSPu8,RSIu8,RDIu8?668 cur.has_REX=TRUE;669 if (tmpa1->reg2&15>7)670 cur.REX|=1;671 if (tmpa1->reg2>=20) //RBPu8,RSPu8,RSIu8,RDIu8?672 cur.has_REX=TRUE;673 if (tmpa1->reg2&7==REG_RBP &&674 !tmpa1->imm_or_off_present && tmpa1->indirect) {675 cur.ModrM|=0x40;676 cur.disp.U8_cnt=1;677 ModrM_complete=TRUE;678 }679 }680 }681 if (!ModrM_complete) {682 if (tmpa1->imm_or_off_present &&683 tmpa1->indirect && tmpa1->reg1==REG_NONE) {684 cur.ModrM=cur.ModrM&0xF8+5;685 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));686 cur.disp.U8_cnt=4;687 if (aotc->seg_size==64)688 cur.disp.imm_flag=FALSE;689 } else {690 if (tmpa1->imm_or_off_present) {691 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));692 if (!cur.disp.num.machine_code &&693 I8_MIN<=cur.disp.num.i<=I8_MAX) {694 cur.ModrM|=0x40;695 cur.disp.U8_cnt=1;696 } else if (aotc->seg_size==16) {697 cur.ModrM|=0x80;698 cur.disp.U8_cnt=2;699 } else {700 cur.ModrM|=0x80;701 cur.disp.U8_cnt=4;702 }703 } else if (!tmpa1->indirect) {704 cur.has_addr_prefix=FALSE;705 cur.ModrM|=0xC0;706 } else {707 if (tmpa1->reg1&7==REG_RBP) {708 cur.ModrM|=0x40;709 cur.disp.U8_cnt=1;710 }711 }712 }713 }714 } else if (ARGT_MOFFS8<=arg1<=ARGT_MOFFS64) {715 MemCpy(&cur.disp.num,&tmpa1->num,sizeof(CAsmNum));716 if (aotc->seg_size==16)717 cur.disp.U8_cnt=2;718 else719 cur.disp.U8_cnt=4;720 cur.has_addr_prefix=FALSE;721 } else if (ARGT_MOFFS8<=arg2<=ARGT_MOFFS64) {722 MemCpy(&cur.disp.num,&tmpa2->num,sizeof(CAsmNum));723 if (aotc->seg_size==16)724 cur.disp.U8_cnt=2;725 else726 cur.disp.U8_cnt=4;727 cur.has_addr_prefix=FALSE;728 } else if (ARGT_IMM8<=arg1<=ARGT_IMM64 ||729 ARGT_UIMM8<=arg1<=ARGT_UIMM64) {730 MemCpy(&cur.imm.num,&tmpa1->num,sizeof(CAsmNum));731 if (arg1==ARGT_IMM8 || arg1==ARGT_UIMM8) cur.imm.U8_cnt=1;732 else if (arg1==ARGT_IMM16 || arg1==ARGT_UIMM16) cur.imm.U8_cnt=2;733 else if (arg1==ARGT_IMM32 || arg1==ARGT_UIMM32) cur.imm.U8_cnt=4;734 else {735 cur.imm.U8_cnt=8;736 cur.REX|=8;737 }738 }739 if (ARGT_IMM8<=arg2<=ARGT_IMM64 ||740 ARGT_UIMM8<=arg2<=ARGT_UIMM64) {741 MemCpy(&cur.imm.num,&tmpa2->num,sizeof(CAsmNum));742 if (arg2==ARGT_IMM8 || arg2==ARGT_UIMM8) cur.imm.U8_cnt=1;743 else if (arg2==ARGT_IMM16 || arg2==ARGT_UIMM16) cur.imm.U8_cnt=2;744 else if (arg2==ARGT_IMM32 || arg2==ARGT_UIMM32) {745 cur.imm.U8_cnt=4;746 if (tmpins->flags&IEF_REX_ONLY_R8_R15 && arg2==ARGT_UIMM32)747 cur.REX&=~8;748 } else {749 cur.imm.U8_cnt=8;750 cur.REX|=8;751 }752 }753 }754 cur.U8_cnt=tmpins->opcode_cnt+cur.disp.U8_cnt+cur.imm.U8_cnt;755 if (cur.has_ModrM) cur.U8_cnt++;756 if (cur.has_SIB) cur.U8_cnt++;757 if (aotc->seg_size==64 && cur.REX&0x40==0x40 &&758 (cur.REX!=0x40 || cur.has_REX) &&759 (cur.REX&7 || !(tmpins->flags&IEF_REX_ONLY_R8_R15 ||760 tmpins->flags&IEF_REX_XOR_LIKE && tmpa1->reg1==tmpa2->reg1 &&761 cur.ModrM&0xC0==0xC0)))762 cur.U8_cnt++;763 if (cur.U8_cnt<best.U8_cnt &&764 !(tmpins->flags & IEF_DONT_SWITCH_MODES &&765 (cur.has_addr_prefix || cur.has_operand_prefix)))766 MemCpy(&best,&cur,sizeof(CAsmIns));767 }768 }769 if (best.U8_cnt<255) {770 tmpins=best.tmpins;771 seg=REG_NONE;772 if (argcnt>1 && aotc->arg2.seg!=REG_NONE && !aotc->arg2.just_seg)773 seg=aotc->arg2.seg;774 else if (argcnt>0 && aotc->arg1.seg!=REG_NONE && !aotc->arg1.just_seg)775 seg=aotc->arg1.seg;776 if (seg!=REG_NONE)777 AOTStoreCodeU8(cc,asm_seg_prefixes[seg]);778 if (best.has_operand_prefix)779 AOTStoreCodeU8(cc,OC_OP_SIZE_PREFIX); //Operand size override780 if (best.has_addr_prefix || aotc->seg_size==16 && cur.has_SIB)781 AOTStoreCodeU8(cc,OC_ADDR_SIZE_PREFIX); //Operand size override782 if (aotc->seg_size==64 && best.REX&0x40==0x40 &&783 (best.REX!=0x40 || best.has_REX) &&784 (best.REX&7||!(tmpins->flags&IEF_REX_ONLY_R8_R15 ||785 tmpins->flags&IEF_REX_XOR_LIKE && tmpa1->reg1==tmpa2->reg1 &&786 best.ModrM&0xC0==0xC0)))787 AOTStoreCodeU8(cc,best.REX);788 for (j=0;j<tmpins->opcode_cnt-1;j++)789 AOTStoreCodeU8(cc,tmpins->opcode[j]);790 AOTStoreCodeU8(cc,best.last_opcode_U8);791 792 if (best.has_ModrM)793 AOTStoreCodeU8(cc,best.ModrM);794 if (best.has_SIB)795 AOTStoreCodeU8(cc,best.SIB);796 797 if (best.disp.U8_cnt) {798 best.disp.rel=aotc->rip+best.disp.U8_cnt+best.imm.U8_cnt;799 if (!AsmStoreNum(cc,&best.disp,1,U8_avail))800 return FALSE;801 }802 803 if (best.imm.U8_cnt) {804 best.imm.rel=aotc->rip+best.imm.U8_cnt;805 if (!AsmStoreNum(cc,&best.imm,1,U8_avail))806 return FALSE;807 }808 if (tmpins->flags&IEF_ENDING_ZERO) //ENTER inst809 AOTStoreCodeU8(cc,0);810 return TRUE;811 }812 LexExcept(cc,"Invalid inst at ");813}814 815U0 PrsAsmDefine(CCmpCtrl *cc,I64 U8_cnt)816{817 Bool is_dup;818 I64 i,dup_val;819 U8 *ptr;820 CAsmNum2 num2;821 num2.U8_cnt=U8_cnt;822 823 while (cc->token && cc->token!=';') {824 num2.num.local_asm_undef_hash=NULL;825 num2.num.glbl_asm_undef_hash=NULL;826 if (cc->token==TK_STR) {827 ptr=cc->cur_str;828 i=cc->cur_str_len-1;829 while (i--)830 AOTStoreCodeU8(cc,*ptr++);831 Lex(cc); //Skip Str832 } else {833 is_dup=FALSE;834 cc->abs_cnts=0;835 cc->asm_undef_hash=NULL;836 cc->flags&=~(CCF_UNRESOLVED+CCF_LOCAL);837 if (!IsLexExpression2Bin(cc,&num2.num.machine_code))838 LexSkipEol(cc);839 else {840 if (cc->abs_cnts.externs)841 LexExcept(cc,"Extern Not Allowed at ");842 if (cc->flags & CCF_UNRESOLVED) {843 if (cc->flags & CCF_LOCAL) {844 num2.num.local_asm_undef_hash=cc->asm_undef_hash;845 cc->asm_undef_hash=NULL;846 } else {847 num2.num.glbl_asm_undef_hash=cc->asm_undef_hash;848 cc->asm_undef_hash=NULL;849 }850 } else {851 i=Call(num2.num.machine_code);852 Free(num2.num.machine_code);853 }854 }855 if (cc->token==TK_IDENT && cc->hash_entry) {856 if (cc->hash_entry->type & HTT_ASM_KEYWORD &&857 cc->hash_entry->user_data0==AKW_DUP) {858 is_dup=TRUE;859 if (Lex(cc)!='(')860 LexExcept(cc,"Expecting '(' at ");861 Lex(cc); //skip (862 dup_val=AsmLexExpression(cc);863 if (cc->token!=')')864 LexExcept(cc,"Expecting ')' at ");865 Lex(cc); //SKIP )866 }867 }868 num2.rel=0;869 num2.imm_flag=TRUE;870 num2.num.abs_cnts=cc->abs_cnts;871 if (is_dup) {872 if (num2.num.local_asm_undef_hash || num2.num.glbl_asm_undef_hash)873 LexExcept(cc,"Undefined DUP cnt at ");874 num2.num.i=dup_val;875 AsmStoreNum(cc,&num2,i,FALSE);876 } else {877 num2.num.i=i;878 AsmStoreNum(cc,&num2,1,FALSE);879 }880 }881 if (cc->token==',')882 Lex(cc);883 }884 if (cc->token!=';')885 LexExcept(cc,"Missing ';' at");886 Lex(cc);887}888 889U0 PrsBinFile(CCmpCtrl *cc)890{891 I64 i,size;892 U8 *buf,*st;893 if (cc->token!=TK_STR)894 LexExcept(cc,"Expecting string at ");895 st=ExtDft(cc->cur_str,"BIN");896 buf=FileRead(st,&size);897 Free(st);898 for (i=0;i<size;i++)899 AOTStoreCodeU8(cc,buf[i]);900 if (Lex(cc)!=';')901 LexExcept(cc,"Missing ';' at");902 Lex(cc);903}904 905U0 PrsAsmBlk(CCmpCtrl *cc,I64 cmp_flags)906{907 CAOTCtrl *aotc=cc->aotc;908 I64 i,j,k,argcnt,909 old_flags=cc->flags & CCF_ASM_EXPRESSIONS;910 CHashOpcode *tmpo;911 CHashExport *tmpex;912 U8 *next_last_label;913 CCodeMisc *g_lb;914 915 aotc->seg_size=64;916 cc->flags|=CCF_ASM_EXPRESSIONS;917 if (!(cmp_flags&CMPF_ONE_ASM_INS)) {918 if (cc->token!='{')919 LexExcept(cc,"Expecting '{' at ");920 Lex(cc);921 }922 while (cc->token && cc->token!='}') {923 AsmLineLst(cc);924 if (cc->token==TK_IDENT && cc->hash_entry) {925 if (cc->hash_entry->type&HTT_ASM_KEYWORD) {926 i=cc->hash_entry->user_data0;927 Lex(cc); //skip keyword928 switch (i) {929 case AKW_IMPORT:930 while (cc->token && cc->token!=';') {931 if (cc->token!=TK_IDENT)932 LexExcept(cc,"Expecting identifier at ");933 else {934 tmpex=NULL;935 tmpex=CAlloc(sizeof(CHashExport));936 tmpex->str=cc->cur_str;937 cc->cur_str=0;938 tmpex->type=HTT_EXPORT_SYS_SYM|HTF_UNRESOLVED;939 HashAdd(tmpex,cc->htc.glbl_hash_table);940 tmpex->type|=HTF_IMPORT;941 if (Lex(cc)==',')942 Lex(cc); //skip ','943 }944 }945 if (cc->token!=';')946 LexExcept(cc,"Missing ';' at");947 Lex(cc); //skip ';';948 break;949 case AKW_ORG:950 if (cc->htc.local_var_lst)951 LexExcept(cc,"ORG not allowed in fun asm blk ");952 if (aotc->org!=INVALID_PTR)953 LexExcept(cc,"Just one org allowed ");954 if (aotc->rip)955 LexExcept(cc,"ORG must be at beginning ");956 aotc->org=AsmLexExpression(cc);957 break;958 case AKW_ALIGN:959 if (cc->htc.local_var_lst)960 LexExcept(cc,"ALIGN not allowed in fun asm blk ");961 i=AsmLexExpression(cc);962 j=Bsf(i);963 if (!i || j!=Bsr(i))964 LexExcept(cc,"ALIGN must be power of two at ");965 if (!(cc->flags&CCF_AOT_COMPILE) && i>8)966 LexExcept(cc,"In JIT mode, max ALIGN is 8 ");967 if (j>aotc->max_align_bits) aotc->max_align_bits=j;968 i=CeilU64(aotc->rip,i);969 if (cc->token!=',')970 LexExcept(cc,"Expecting ',' at ");971 Lex(cc);972 k=AsmLexExpression(cc);973 for (j=aotc->rip;j<i;j++)974 AOTStoreCodeU8(cc,k);975 break;976 case AKW_DU8:977 PrsAsmDefine(cc,1);978 break;979 case AKW_DU16:980 PrsAsmDefine(cc,2);981 break;982 case AKW_DU32:983 PrsAsmDefine(cc,4);984 break;985 case AKW_DU64:986 PrsAsmDefine(cc,8);987 break;988 case AKW_BINFILE:989 PrsBinFile(cc);990 break;991 case AKW_LIST:992 aotc->lst=TRUE;993 break;994 case AKW_NOLIST:995 aotc->lst=FALSE;996 break;997 case AKW_USE16:998 aotc->seg_size=16;999 break;1000 case AKW_USE32:1001 aotc->seg_size=32;1002 break;1003 case AKW_USE64:1004 aotc->seg_size=64;1005 break;1006 default:1007 LexExcept(cc,"Syntax error at ");1008 }1009 } else if (cc->hash_entry->type & HTT_OPCODE) {1010 tmpo=cc->hash_entry;1011 Lex(cc); //skip opcode1012 argcnt=0;1013 if (tmpo->ins[0].arg1) {1014 argcnt++;1015 if (ARGT_REL8<=tmpo->ins[0].arg1<=ARGT_REL32)1016 PrsAsmArg(cc,&aotc->arg1,TRUE);1017 else1018 PrsAsmArg(cc,&aotc->arg1,FALSE);1019 if (tmpo->ins[0].arg2) {1020 argcnt++;1021 if (cc->token!=',')1022 LexExcept(cc,"Expecting ',' at ");1023 else {1024 Lex(cc); //skip ','1025 if (ARGT_REL8<=tmpo->ins[0].arg2<=ARGT_REL32)1026 PrsAsmArg(cc,&aotc->arg2,TRUE);1027 else1028 PrsAsmArg(cc,&aotc->arg2,FALSE);1029 }1030 }1031 }1032 PrsAsmInst(cc,tmpo,argcnt);1033 } else if (cc->hash_entry->type & HTT_EXPORT_SYS_SYM) {1034 if (Btr(&cc->hash_entry->type,HTf_UNRESOLVED)) {1035 if (cc->hash_entry->type & HTF_LOCAL) {1036 cc->hash_entry(CHashExport *)->val=aotc->rip;1037 if (Lex(cc)!=':')1038 LexExcept(cc,"Expecting ':' at ");1039 Lex(cc);1040 } else {1041 if (cc->hash_entry->type & HTF_IMPORT)1042 LexExcept(cc,"attempt to define import at ");1043 cc->hash_entry(CHashExport *)->val=aotc->rip;1044 next_last_label=cc->hash_entry->str;1045 Lex(cc); //Skip cur_str1046 if (cc->token!=':' && cc->token!=TK_DBL_COLON)1047 LexExcept(cc,"Expecting ':' at ");1048 if (cc->token==TK_DBL_COLON) {1049 cc->hash_entry->type|=HTF_EXPORT;1050 HashSrcFileSet(cc,cc->hash_entry);1051 1052 AOTLocalsResolve(cc);1053 aotc->last_label=next_last_label;1054 }1055 Lex(cc);1056 }1057 } else if (cc->hash_entry(CHashExport *)->val==aotc->rip) {1058 Lex(cc); //Skip cur_str1059 if (cc->token!=':' && cc->token!=TK_DBL_COLON)1060 LexExcept(cc,"Expecting ':' at ");1061 Lex(cc);1062 } else1063 LexExcept(cc,"Redefinition at ");1064 } else1065 LexExcept(cc,"Syntax error at ");1066 } else if (cc->token==TK_IDENT) {1067 tmpex=CAlloc(sizeof(CHashExport));1068 tmpex->str=cc->cur_str;1069 cc->cur_str=0;1070 tmpex->type=HTT_EXPORT_SYS_SYM;1071 tmpex->val=aotc->rip;1072 Lex(cc); //Skip cur_str1073 if (cc->token!=':' && cc->token!=TK_DBL_COLON)1074 LexExcept(cc,"Expecting ':' at ");1075 else {1076 if (*tmpex->str=='@' && tmpex->str[1]=='@') {1077 if (cc->token==TK_DBL_COLON)1078 LexExcept(cc,"No local glbl exports at ");1079 HashAdd(tmpex,cc->htc.local_hash_table);1080 } else1081 HashAdd(tmpex,cc->htc.glbl_hash_table);1082 if (cc->htc.local_var_lst) {//AsmBlk in fun? Also add goto-like label.1083 if (!(g_lb=COCGoToLabelFind(cc,tmpex->str))) {1084 g_lb=COCMiscNew(cc,CMT_ASM_LABEL);1085 g_lb->str=StrNew(tmpex->str);1086 } else if (g_lb->flags&CMF_DEFINED)1087 LexExcept(cc,"Duplicate goto label at ");1088 g_lb->type=CMT_ASM_LABEL;1089 g_lb->flags|=CMF_DEFINED;1090 g_lb->rip=aotc->rip;1091 g_lb->use_cnt++; //Disable warning on unused labels.1092 ICAdd(cc,IC_LABEL,g_lb,0);1093 }1094 if (cc->token==TK_DBL_COLON) {1095 tmpex->type|=HTF_EXPORT;1096 HashSrcFileSet(cc,tmpex);1097 1098 AOTLocalsResolve(cc);1099 aotc->last_label=tmpex->str;1100 }1101 Lex(cc);1102 }1103 } else if (cc->token==';')1104 Lex(cc);1105 else1106 LexExcept(cc,"Syntax error at ");1107 if (cmp_flags&CMPF_ONE_ASM_INS && (cc->token!=TK_IDENT ||1108 !(tmpo=cc->hash_entry) ||1109 !(tmpo->type&(HTT_OPCODE|HTT_ASM_KEYWORD))))1110 break;1111 }1112 AOTLocalsResolve(cc);1113 aotc->lst=FALSE;1114 cc->flags&=cc->flags&~CCF_ASM_EXPRESSIONS|old_flags;1115}1116 