From d280ed6e8b3a442fec461e2d9edb7fa0cd0c332d Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 11 Sep 2005 10:01:54 +0000 Subject: [PATCH] * continued to work on arm binary writer, started to fix operand matching git-svn-id: trunk@1073 - --- compiler/arm/aasmcpu.pas | 158 +++++++++++++++++++++++++++++++++++---- compiler/arm/armins.dat | 24 +++--- compiler/arm/armnop.inc | 2 +- compiler/arm/armtab.inc | 54 ++----------- compiler/arm/cgcpu.pas | 25 ------- compiler/arm/cpubase.pas | 24 ++++++ 6 files changed, 186 insertions(+), 101 deletions(-) diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas index 2fb343d5d1..972d07cec2 100644 --- a/compiler/arm/aasmcpu.pas +++ b/compiler/arm/aasmcpu.pas @@ -49,8 +49,10 @@ uses OT_NEAR = $00000040; OT_SHORT = $00000080; OT_BITSTINY = $00000100; { fpu constant } + OT_BITSSHIFTER = + $00000200; - OT_SIZE_MASK = $000000FF; { all the size attributes } + OT_SIZE_MASK = $000003FF; { all the size attributes } OT_NON_SIZE = longint(not OT_SIZE_MASK); OT_SIGNED = $00000100; { the operand need to be signed -128-127 } @@ -59,15 +61,21 @@ uses { reverse effect in FADD, FSUB &c } OT_COLON = $00000400; + OT_SHIFTEROP = $00000800; OT_REGISTER = $00001000; OT_IMMEDIATE = $00002000; OT_REGLIST = $00008000; OT_IMM8 = $00002001; - OT_IMM16 = $00002002; + OT_IMM24 = $00002002; OT_IMM32 = $00002004; OT_IMM64 = $00002008; OT_IMM80 = $00002010; OT_IMMTINY = $00002100; + OT_IMMSHIFTER= $00002200; + OT_IMMEDIATE24 = OT_IMM24; + OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER; + OT_SHIFTIMMEDIATE = OT_SHIFTIMM; + OT_IMMEDIATEFPU = OT_IMMTINY; OT_REGMEM = $00200000; { for r/m, ie EA, operands } @@ -83,6 +91,19 @@ uses OT_MEM32 = $00204004; OT_MEM64 = $00204008; OT_MEM80 = $00204010; + { word/byte load/store } + OT_AM2 = $00010000; + { misc ld/st operations } + OT_AM3 = $00020000; + { multiple ld/st operations } + OT_AM4 = $00040000; + { co proc. ld/st operations } + OT_AM5 = $00080000; + OT_AMMASK = $000f0000; + + OT_MEMORYAM4 = OT_MEMORY or OT_AM4; + OT_MEMORYAM5 = OT_MEMORY or OT_AM5; + OT_FPUREG = $01000000; { floating point stack registers } OT_REG_SMASK = $00070000; { special register operands: these may be treated differently } { a mask for the following } @@ -853,6 +874,8 @@ implementation begin s:=s+'mem'; addsize:=true; + if (ot and OT_AM2)<>0 then + s:=s+' am2'; end else s:=s+'???'; @@ -867,6 +890,9 @@ implementation else if (ot and OT_BITS32)<>0 then s:=s+'32' + else + if (ot and OT_BITSSHIFTER)<>0 then + s:=s+'shifter' else s:=s+'??'; { signed } @@ -909,6 +935,11 @@ implementation function taicpu.Pass1(offset:longint):longint; + var + ldr2op : array[PF_B..PF_T] of tasmop = ( + A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT); + str2op : array[PF_B..PF_T] of tasmop = ( + A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT); begin Pass1:=0; { Save the old offset and set the new offset } @@ -918,6 +949,27 @@ implementation exit; { set the file postion } aktfilepos:=fileinfo; + + { tranlate LDR+postfix to complete opcode } + if (opcode=A_LDR) and (oppostfix<>PF_None) then + begin + if (oppostfix in [low(ldr2op)..high(ldr2op)]) then + opcode:=ldr2op[oppostfix] + else + internalerror(2005091001); + if opcode=A_None then + internalerror(2005091004); + end + else if (opcode=A_STR) and (oppostfix<>PF_None) then + begin + if (oppostfix in [low(str2op)..high(str2op)]) then + opcode:=str2op[oppostfix] + else + internalerror(2005091002); + if opcode=A_None then + internalerror(2005091003); + end; + { Get InsEntry } if FindInsEntry then begin @@ -963,6 +1015,7 @@ implementation procedure taicpu.create_ot; var i,l,relsize : longint; + dummy : byte; begin if ops=0 then exit; @@ -979,7 +1032,7 @@ implementation begin case getregtype(reg) of R_INTREGISTER: - ot:=OT_REG32; + ot:=OT_REG32 or OT_SHIFTEROP; R_FPUREGISTER: ot:=OT_FPUREG; else @@ -1000,6 +1053,38 @@ implementation if (ref^.base=NR_NO) and (ref^.index=NR_NO) then ot:=ot or OT_MEM_OFFS; { if we need to fix a reference, we do it here } + + { determine possible address modes } + if (ref^.base<>NR_NO) and + ( + ( + (ref^.index=NR_NO) and + (ref^.shiftmode=SM_None) and + (ref^.offset>=-4097) and + (ref^.offset<=4097) + ) or + ( + (ref^.shiftmode=SM_None) and + (ref^.offset=0) + ) or + ( + (ref^.index<>NR_NO) and + (ref^.shiftmode<>SM_None) and + (ref^.shiftimm<=31) and + (ref^.offset=0) + ) + ) then + ot:=ot or OT_AM2; + + if (ref^.index<>NR_NO) and + (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and + ( + (ref^.base=NR_NO) and + (ref^.shiftmode=SM_None) and + (ref^.offset=0) + ) then + ot:=ot or OT_AM4; + end else begin @@ -1008,8 +1093,8 @@ implementation inc(l,ref^.symbol.address); if (not assigned(ref^.symbol) or ((ref^.symbol.currbind<>AB_EXTERNAL) and (ref^.symbol.address<>0))) and - (relsize>=-128) and (relsize<=127) then - ot:=OT_IMM32 or OT_SHORT + (relsize>=-33554428) and (relsize<=33554428) and (relsize mod 4=0) then + ot:=OT_IMM24 else ot:=OT_IMM32 or OT_NEAR; end; @@ -1026,14 +1111,10 @@ implementation top_const : begin ot:=OT_IMMEDIATE; - { fixme !!!! - if opsize=S_NO then - message(asmr_e_invalid_opcode_and_operand); - if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then - ot:=OT_IMM8 or OT_SIGNED + if is_shifter_const(val,dummy) then + ot:=OT_IMMSHIFTER else - ot:=OT_IMMEDIATE or opsize_2_type[i,opsize]; - } + ot:=OT_IMM32 end; top_none : begin @@ -1043,6 +1124,7 @@ implementation end; top_shifterop: begin + ot:=OT_SHIFTEROP; end; else internalerror(200402261); @@ -1077,6 +1159,7 @@ implementation siz : array[0..3] of longint; begin Matches:=100; + writeln(getstring,'---'); { Check the opcode and operands } if (p^.opcode<>opcode) or (p^.ops<>ops) then @@ -1111,6 +1194,51 @@ implementation end; end; + { check postfixes: + the existance of a certain postfix requires a + particular code } + + { update condition flags + or floating point single } + if (oppostfix=PF_S) and + not(p^.code[0] in []) then + begin + Matches:=0; + exit; + end; + + { floating point size } + if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and + not(p^.code[0] in []) then + begin + Matches:=0; + exit; + end; + + { multiple load/store address modes } + if (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and + not(p^.code[0] in [ + // stm,ldm + #$26 + ]) then + begin + Matches:=0; + exit; + end; + + { we shouldn't see any opsize prefixes here } + if (oppostfix in [PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T]) then + begin + Matches:=0; + exit; + end; + + if (roundingmode<>RM_None) and not(p^.code[0] in []) then + begin + Matches:=0; + exit; + end; + { Check operand sizes } { as default an untyped size can get all the sizes, this is different from nasm, but else we need to do a lot checking which opcodes want @@ -1559,7 +1687,7 @@ static char *CC[] = out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG); return; - + case 0xC: // CMP Rn,Rm case 0xD: // CMP Rn,Rm,Rs @@ -1735,7 +1863,7 @@ static char *CC[] = case 0x14: // MUL Rd,Rm,Rs case 0x15: // MULA Rd,Rm,Rs,Rn ++codes; - + bytes[0] = c | *codes++; bytes[1] = *codes++; @@ -2027,7 +2155,7 @@ static char *CC[] = data = -8; else data = 0; - + if (data < 0) { data = -data; diff --git a/compiler/arm/armins.dat b/compiler/arm/armins.dat index d9f34f4a1f..aa1d0f0879 100644 --- a/compiler/arm/armins.dat +++ b/compiler/arm/armins.dat @@ -125,11 +125,11 @@ reg32,reg32,imm \7\x3\xC0 ARM7 [BLcc] mem32 \1\x0B ARM7 -imm32 \1\x0B ARM7 +imm24 \1\x0B ARM7 [BLX] mem32 \xff ARM7 -imm32 \xff ARM7 +imm24 \xff ARM7 [BKPTcc] @@ -186,7 +186,7 @@ reg32,reg32,imm \7\x2\x20 ARM7 reg32,reg32 \321\300\1\x11\101 ARM7 [LDMcc] -reg32,reglist \x26\x81 ARM7 +memam4,reglist \x26\x81 ARM7 [LDRBTcc] @@ -235,10 +235,10 @@ reg32,mem32 \320\301\1\x13\110 ARM7 reg32,reg32,reg32,reg32 \x15\x00\x20\x90 ARM7 [MOVcc] -reg32,reg32 \x8\x1\xA0 ARM7 -reg32,reg32,reg32 \x9\x1\xA0 ARM7 -reg32,reg32,imm \xA\x1\xA0 ARM7 -reg32,imm \xB\x3\xA0 ARM7 +reg32,shifterop \x8\x1\xA0 ARM7 +; reg32,reg32,reg32 \x9\x1\xA0 ARM7 +; reg32,reg32,imm \xA\x1\xA0 ARM7 +; reg32,imm \xB\x3\xA0 ARM7 ; [MRC] ; reg32,reg32 \321\301\1\x13\110 ARM7 @@ -326,7 +326,7 @@ reg32,reg32,reg32,reg32 \x16\x00\xC0\x90 ARM7 [STFcc] [STMcc] -reg32,reglist \x26\x80 ARM7 +memam4,reglist \x26\x80 ARM7 [STRcc] reg32,imm32 \x17\x05\x00 ARM7 @@ -349,10 +349,10 @@ reg32,reg32,reg32 \x25\x00\xB0 ARM7 [STRTcc] [SUBcc] -reg32,reg32,reg32 \4\x0\x40 ARM7 -reg32,reg32,reg32,reg32 \5\x0\x40 ARM7 -reg32,reg32,reg32,imm \6\x0\x40 ARM7 -reg32,reg32,imm \7\x2\x40 ARM7 +reg32,reg32,shiftimm \4\x0\x40 ARM7 +; reg32,reg32,reg32,reg32 \5\x0\x40 ARM7 +; reg32,reg32,reg32,imm \6\x0\x40 ARM7 +; reg32,reg32,imm \7\x2\x40 ARM7 [SWIcc] imm \2\x0F ARM7 diff --git a/compiler/arm/armnop.inc b/compiler/arm/armnop.inc index 54ceb5804f..1f45135036 100644 --- a/compiler/arm/armnop.inc +++ b/compiler/arm/armnop.inc @@ -1,2 +1,2 @@ { don't edit, this file is generated from armins.dat } -117; +111; diff --git a/compiler/arm/armtab.inc b/compiler/arm/armtab.inc index ac2e08ba0e..af0539515d 100644 --- a/compiler/arm/armtab.inc +++ b/compiler/arm/armtab.inc @@ -143,7 +143,7 @@ ( opcode : A_BL; ops : 1; - optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none); + optypes : (ot_immediate24,ot_none,ot_none,ot_none); code : #1#11; flags : if_arm7 ), @@ -157,7 +157,7 @@ ( opcode : A_BLX; ops : 1; - optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none); + optypes : (ot_immediate24,ot_none,ot_none,ot_none); code : #15#15; flags : if_arm7 ), @@ -276,7 +276,7 @@ ( opcode : A_LDM; ops : 2; - optypes : (ot_reg32,ot_reglist,ot_none,ot_none); + optypes : (ot_memoryam5,ot_reglist,ot_none,ot_none); code : #38#129; flags : if_arm7 ), @@ -423,31 +423,10 @@ ( opcode : A_MOV; ops : 2; - optypes : (ot_reg32,ot_reg32,ot_none,ot_none); + optypes : (ot_reg32,ot_shifterop,ot_none,ot_none); code : #8#1#160; flags : if_arm7 ), - ( - opcode : A_MOV; - ops : 3; - optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none); - code : #9#1#160; - flags : if_arm7 - ), - ( - opcode : A_MOV; - ops : 3; - optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none); - code : #10#1#160; - flags : if_arm7 - ), - ( - opcode : A_MOV; - ops : 2; - optypes : (ot_reg32,ot_immediate,ot_none,ot_none); - code : #11#3#160; - flags : if_arm7 - ), ( opcode : A_MUL; ops : 3; @@ -633,7 +612,7 @@ ( opcode : A_STM; ops : 2; - optypes : (ot_reg32,ot_reglist,ot_none,ot_none); + optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none); code : #38#128; flags : if_arm7 ), @@ -703,31 +682,10 @@ ( opcode : A_SUB; ops : 3; - optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none); + optypes : (ot_reg32,ot_reg32,ot_shiftimmediate,ot_none); code : #4#0#64; flags : if_arm7 ), - ( - opcode : A_SUB; - ops : 4; - optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32); - code : #5#0#64; - flags : if_arm7 - ), - ( - opcode : A_SUB; - ops : 4; - optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate); - code : #6#0#64; - flags : if_arm7 - ), - ( - opcode : A_SUB; - ops : 3; - optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none); - code : #7#2#64; - flags : if_arm7 - ), ( opcode : A_SWI; ops : 1; diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 884d6e3b93..6474a63b44 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -118,8 +118,6 @@ unit cgcpu; OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT, C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI); - function is_shifter_const(d : aint;var imm_shift : byte) : boolean; - function get_fpu_postfix(def : tdef) : toppostfix; implementation @@ -546,29 +544,6 @@ unit cgcpu; end; - function rotl(d : dword;b : byte) : dword; - begin - result:=(d shr (32-b)) or (d shl b); - end; - - - function is_shifter_const(d : aint;var imm_shift : byte) : boolean; - var - i : longint; - begin - for i:=0 to 15 do - begin - if (dword(d) and not(rotl($ff,i*2)))=0 then - begin - imm_shift:=i*2; - result:=true; - exit; - end; - end; - result:=false; - end; - - procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aint;reg : tregister); var imm_shift : byte; diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas index 2e6d16435b..097854076b 100644 --- a/compiler/arm/cpubase.pas +++ b/compiler/arm/cpubase.pas @@ -369,6 +369,8 @@ unit cpubase; procedure shifterop_reset(var so : tshifterop); function is_pc(const r : tregister) : boolean; + function is_shifter_const(d : aint;var imm_shift : byte) : boolean; + implementation uses @@ -493,4 +495,26 @@ unit cpubase; end; + function rotl(d : dword;b : byte) : dword; + begin + result:=(d shr (32-b)) or (d shl b); + end; + + + function is_shifter_const(d : aint;var imm_shift : byte) : boolean; + var + i : longint; + begin + for i:=0 to 15 do + begin + if (dword(d) and not(rotl($ff,i*2)))=0 then + begin + imm_shift:=i*2; + result:=true; + exit; + end; + end; + result:=false; + end; + end.