diff options
Diffstat (limited to 'lib/hipe/sparc/hipe_sparc_encode.erl')
-rw-r--r-- | lib/hipe/sparc/hipe_sparc_encode.erl | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/lib/hipe/sparc/hipe_sparc_encode.erl b/lib/hipe/sparc/hipe_sparc_encode.erl new file mode 100644 index 0000000000..8a28f33ab9 --- /dev/null +++ b/lib/hipe/sparc/hipe_sparc_encode.erl @@ -0,0 +1,476 @@ +%%% -*- erlang-indent-level: 2 -*- +%%% +%%% %CopyrightBegin% +%%% +%%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%%% +%%% The contents of this file are subject to the Erlang Public License, +%%% Version 1.1, (the "License"); you may not use this file except in +%%% compliance with the License. You should have received a copy of the +%%% Erlang Public License along with this software. If not, it can be +%%% retrieved online at http://www.erlang.org/. +%%% +%%% Software distributed under the License is distributed on an "AS IS" +%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%%% the License for the specific language governing rights and limitations +%%% under the License. +%%% +%%% %CopyrightEnd% +%%% +%%% Encode symbolic SPARC instructions to binary form. +%%% Copyright (C) 2007-2008 Mikael Pettersson + +-module(hipe_sparc_encode). + +-export([insn_encode/2]). + +%%-define(TESTING,1). +-ifdef(TESTING). +-export([dotest/0, dotest/1]). +-endif. + +-define(ASSERT(G), + if G -> []; + true -> exit({assertion_failed,?MODULE,?LINE,??G}) + end). + +bf(LeftBit, RightBit, Value) -> + ?ASSERT(32 > LeftBit), + ?ASSERT(LeftBit >= RightBit), + ?ASSERT(RightBit >= 0), + ?ASSERT(Value >= 0), + ?ASSERT(Value < (1 bsl ((LeftBit - RightBit) + 1))), + Value bsl RightBit. + +-define(BF(LB,RB,V), bf(LB,RB,V)). +-define(BIT(Pos,Val), ?BF(Pos,Pos,Val)). +%%-define(BITS(N,Val), ?BF(N,0,Val)). + +%%% +%%% Instruction Formats +%%% + +format1(Disp30) -> + ?BIT(30,1) bor ?BF(29,0,Disp30). + +format2a(Rd, Op2, Imm22) -> + ?BF(29,25,Rd) bor ?BF(24,22,Op2) bor ?BF(21,0,Imm22). + +format2b(A, Cond, Op2, Disp22) -> + ?BIT(29,A) bor ?BF(28,25,Cond) bor ?BF(24,22,Op2) bor ?BF(21,0,Disp22). + +format2c(A, Cond, Op2, CC1, CC0, P, Disp19) -> + ?BIT(29,A) bor ?BF(28,25,Cond) bor ?BF(24,22,Op2) bor ?BIT(21,CC1) + bor ?BIT(20,CC0) bor ?BIT(19,P) bor ?BF(18,0,Disp19). + +format2d(A, RCond, Op2, P, Rs1, Disp16) -> + D16Hi = Disp16 bsr 14, + D16Lo = Disp16 band 16#3FFF, + ?BIT(29,A) bor ?BF(27,25,RCond) bor ?BF(24,22,Op2) bor ?BF(21,20,D16Hi) + bor ?BIT(19,P) bor ?BF(18,14,Rs1) bor ?BF(13,0,D16Lo). + +format3common(Op, Rd, Op3, Rs1) -> % format 3, bits 31..14 + ?BF(31,30,Op) bor ?BF(29,25,Rd) bor ?BF(24,19,Op3) bor ?BF(18,14,Rs1). + +format3a(Op, Rd, Op3, Rs1, Rs2) -> + format3common(Op, Rd, Op3, Rs1) bor ?BF(4,0,Rs2). + +format3ax(Op, Rd, Op3, Rs1, Rs2) -> + format3a(Op, Rd, Op3, Rs1, Rs2) bor ?BIT(12,1). + +format3b(Op, Rd, Op3, Rs1, Simm13) -> + format3common(Op, Rd, Op3, Rs1) bor ?BIT(13,1) bor ?BF(12,0,Simm13). + +format3b32(Op, Rd, Op3, Rs1, Shcnt32) -> + format3a(Op, Rd, Op3, Rs1, Shcnt32) bor ?BIT(13,1). + +format3b64(Op, Rd, Op3, Rs1, Shcnt64) -> + format3common(Op, Rd, Op3, Rs1) bor ?BIT(13,1) bor ?BF(5,0,Shcnt64). + +format3ab(Op, {r,Rd}, Op3, {r,Rs1}, Src2) -> + case Src2 of + {r,Rs2} -> + format3a(Op, Rd, Op3, Rs1, Rs2); + {simm13,Simm13} -> + format3b(Op, Rd, Op3, Rs1, Simm13) + end. + +format3ab({Rs1,Src2,Rd}, Op3, Op) -> format3ab(Op, Rd, Op3, Rs1, Src2). + +-ifdef(notdef). +format3c(Op, Rd, Op3, Rs1, Opf, Rs2) -> + format3h(Op, Rd, Op3, Rs1) bor (Opf bsl 5) bor Rs2. + +format3d(Op, Rd, Op3, Rs1, I, Rs2) -> + format3h(Op, Rd, Op3, Rs1) bor (I bsl 13) bor Rs2. +-endif. + +%%% +%%% Instruction Operands +%%% + +'cond'(Cond) -> + case Cond of + 'n' -> 2#0000; + 'e' -> 2#0001; + 'le' -> 2#0010; + 'l' -> 2#0011; + 'leu' -> 2#0100; + 'lu' -> 2#0101; % a.k.a. 'cs' + 'neg' -> 2#0110; + 'vs' -> 2#0111; + 'a' -> 2#1000; + 'ne' -> 2#1001; + 'g' -> 2#1010; + 'ge' -> 2#1011; + 'gu' -> 2#1100; + 'geu' -> 2#1101; % a.k.a. 'cc' + 'pos' -> 2#1110; + 'vc' -> 2#1111 + end. + +rcond(RCond) -> + case RCond of + 'z' -> 2#001; + 'lez' -> 2#010; + 'lz' -> 2#011; + 'nz' -> 2#101; + 'gz' -> 2#110; + 'gez' -> 2#111 + end. + +pred(Pred) -> + case Pred of + 'pt' -> 1; + 'pn' -> 0 + end. + +%%% +%%% Branch Instructions +%%% + +call({disp30,Disp30}) -> + format1(Disp30). + +ba({disp22,Disp22}) -> % V7 Bicc, only used for unconditional branches + format2b(0, 'cond'('a'), 2#010, Disp22). + +bp({{'cond',Cond},{pred,Pred},{disp19,Disp19}}) -> + %% XXX: sparc64 will need CC1=1 here + format2c(0, 'cond'(Cond), 2#001, 0, 0, pred(Pred), Disp19). + +br({{rcond,RCond},{pred,Pred},{r,Rs1},{disp16,Disp16}}) -> + format2d(0, rcond(RCond), 2#011, pred(Pred), Rs1, Disp16). + +%%% +%%% Integer Arithmetic Instructions +%%% + +alu(Opnds, Op3) -> format3ab(Opnds, Op3, 2#10). + +add(Opnds) -> alu(Opnds, 2#000000). +addcc(Opnds) -> alu(Opnds, 2#010000). +%%addc(Opnds) -> alu(Opnds, 2#001000). +%%addccc(Opnds) -> alu(Opnds, 2#011000). + +sub(Opnds) -> alu(Opnds, 2#000100). +subcc(Opnds) -> alu(Opnds, 2#010100). +%%subc(Opnds) -> alu(Opnds, 2#001100). % XXX: hipe_sparc_op has bug here +%%subccc(Opnds) -> alu(Opnds, 2#011100). % XXX: hipe_sparc_op has bug here + +%%taddcc(Opnds) -> alu(Opnds, 2#100000). +%%taddcctv(Opnds) -> alu(Opnds, 2#100010). + +%%tsubcc(Opnds) -> alu(Opnds, 2#100001). +%%tsubcctv(Opnds) -> alu(Opnds, 2#100011). + +mulx(Opnds) -> alu(Opnds, 2#001001). +%%sdivx(Opnds) -> alu(Opnds, 2#101101). +%%udivx(Opnds) -> alu(Opnds, 2#001101). + +%%umul(Opnds) -> alu(Opnds, 2#001010). +smul(Opnds) -> alu(Opnds, 2#001011). +%%umulcc(Opnds) -> alu(Opnds, 2#011010). +%%smulcc(Opnds) -> alu(Opnds, 2#011011). + +'and'(Opnds) -> alu(Opnds, 2#000001). +andcc(Opnds) -> alu(Opnds, 2#010001). +%%andn(Opnds) -> alu(Opnds, 2#000101). +%%andncc(Opnds) -> alu(Opnds, 2#010101). + +'or'(Opnds) -> alu(Opnds, 2#000010). +orcc(Opnds) -> alu(Opnds, 2#010010). +%%orn(Opnds) -> alu(Opnds, 2#000110). +%%orncc(Opnds) -> alu(Opnds, 2#010110). + +'xor'(Opnds) -> alu(Opnds, 2#000011). +xorcc(Opnds) -> alu(Opnds, 2#010011). +%%xnor(Opnds) -> alu(Opnds, 2#000111). +%%xnorcc(Opnds) -> alu(Opnds, 2#010111). + +shift32({{r,Rs1},Src2,{r,Rd}}, Op3) -> + case Src2 of + {r,Rs2} -> + format3a(2#10, Rd, Op3, Rs1, Rs2); + {uimm5,Shcnt32} -> + format3b32(2#10, Rd, Op3, Rs1, Shcnt32) + end. + +shift64({{r,Rs1},Src2,{r,Rd}}, Op3) -> + case Src2 of + {r,Rs2} -> + format3ax(2#10, Rd, Op3, Rs1, Rs2); + {uimm6,Shcnt64} -> + format3b64(2#10, Rd, Op3, Rs1, Shcnt64) + end. + +sll(Opnds) -> shift32(Opnds, 2#100101). +sllx(Opnds) -> shift64(Opnds, 2#100101). +srl(Opnds) -> shift32(Opnds, 2#100110). +srlx(Opnds) -> shift64(Opnds, 2#100110). +sra(Opnds) -> shift32(Opnds, 2#100111). +srax(Opnds) -> shift64(Opnds, 2#100111). + +jmpl(Opnds) -> alu(Opnds, 2#111000). + +rd({y,{r,Rd}}) -> format3a(2#10, Rd, 2#101000, 0, 0). + +sethi({{uimm22,UImm22},{r,Rd}}) -> format2a(Rd, 2#100, UImm22). + +ld(Opnds, Op3) -> format3ab(Opnds, Op3, 2#11). + +ldsb(Opnds) -> ld(Opnds, 2#001001). +ldsh(Opnds) -> ld(Opnds, 2#001010). +ldsw(Opnds) -> ld(Opnds, 2#001000). +ldub(Opnds) -> ld(Opnds, 2#000001). +lduh(Opnds) -> ld(Opnds, 2#000010). +lduw(Opnds) -> ld(Opnds, 2#000000). +ldx(Opnds) -> ld(Opnds, 2#001011). +%%ldd(Opnds) -> ld(Opnds, 2#000011). + +st({Rd,Rs1,Src2}, Op3) -> format3ab(2#11, Rd, Op3, Rs1, Src2). + +stb(Opnds) -> st(Opnds, 2#000101). +%%sth(Opnds) -> st(Opnds, 2#000110). +stw(Opnds) -> st(Opnds, 2#000100). +stx(Opnds) -> st(Opnds, 2#001110). +%%std(Opnds) -> st(Opnds, 2#000111). + +%%% +%%% Floating-Point Instructions +%%% + +format3f(Rd, Rs1, Opf, Rs2) -> + format3a(2#10, Rd, 2#110100, Rs1, Rs2) bor ?BF(13,5,Opf). + +fpop1binary(Opf, {{fr,Rs1},{fr,Rs2},{fr,Rd}}) -> + format3f(Rd, Rs1, Opf, Rs2). + +faddd(Opnds) -> fpop1binary(2#001000010, Opnds). +fdivd(Opnds) -> fpop1binary(2#001001110, Opnds). +fmuld(Opnds) -> fpop1binary(2#001001010, Opnds). +fsubd(Opnds) -> fpop1binary(2#001000110, Opnds). + +fpop1unary(Opf, {{fr,Rs2},{fr,Rd}}) -> + format3f(Rd, 0, Opf, Rs2). + +fitod(Opnds) -> fpop1unary(2#011001000, Opnds). +fmovd(Opnds) -> fpop1unary(2#000000010, Opnds). +fnegd(Opnds) -> fpop1unary(2#000000110, Opnds). + +ldf({{r,Rs1},{simm13,Simm13},{fr,Rd}}) -> + format3b(2#11, Rd, 2#100000, Rs1, Simm13). + +stf({{fr,Rd},{r,Rs1},{simm13,Simm13}}) -> + format3b(2#11, Rd, 2#100100, Rs1, Simm13). + +-ifdef(notdef). +fpop1(Rs1,Opf,Rs2,Rd) -> format3a(2#10, Rd, 2#110100, Rs1, Opf, Rs2). +%% fpop2(Rs1,Opf,Rs2,Rd) -> format3a(2#10, Rd, 2#110101, Rs1, Opf, Rs2). + +%% fxtos(Rs2, Rd) -> fpop1(0,2#010000100,Rs2,Rd). +%% fxtod(Rs2, Rd) -> fpop1(0,2#010001000,Rs2,Rd). +%% fxtoq(Rs2, Rd) -> fpop1(0,2#010001100,Rs2,Rd). +fitos(Rs2, Rd) -> fpop1(0,2#011000100,Rs2,Rd). +fitoq(Rs2, Rd) -> fpop1(0,2#011001100,Rs2,Rd). + +%% fstox(Rs2, Rd) -> fpop1(0,2#010000001,Rs2,Rd). +%% fdtox(Rs2, Rd) -> fpop1(0,2#010000010,Rs2,Rd). +%% fqtox(Rs2, Rd) -> fpop1(0,2#010000011,Rs2,Rd). +%% fstoi(Rs2, Rd) -> fpop1(0,2#011010001,Rs2,Rd). +%% fdtoi(Rs2, Rd) -> fpop1(0,2#011010010,Rs2,Rd). +%% fqtoi(Rs2, Rd) -> fpop1(0,2#011010011,Rs2,Rd). + +%% fstod(Rs2, Rd) -> fpop1(0,2#011001001,Rs2,Rd). +%% fstoq(Rs2, Rd) -> fpop1(0,2#011001101,Rs2,Rd). +%% fdtos(Rs2, Rd) -> fpop1(0,2#011000110,Rs2,Rd). +%% fdtoq(Rs2, Rd) -> fpop1(0,2#011001110,Rs2,Rd). +%% fqtos(Rs2, Rd) -> fpop1(0,2#011000111,Rs2,Rd). +%% fqtod(Rs2, Rd) -> fpop1(0,2#011001011,Rs2,Rd). + +fmovs(Rs2, Rd) -> fpop1(0,2#000000001,Rs2,Rd). +fnegs(Rs2, Rd) -> fpop1(0,2#000000101,Rs2,Rd). +fabss(Rs2, Rd) -> fpop1(0,2#000001001,Rs2,Rd). +fabsd(Rs2, Rd) -> fpop1(0,2#000001010,Rs2,Rd). +fmovq(Rs2, Rd) -> fpop1(0,2#000000011,Rs2,Rd). +fnegq(Rs2, Rd) -> fpop1(0,2#000000111,Rs2,Rd). +fabsq(Rs2, Rd) -> fpop1(0,2#000001011,Rs2,Rd). + +%% fsqrts(Rs2, Rd) -> fpop1(0,2#000101001,Rs2,Rd). +%% fsqrtd(Rs2, Rd) -> fpop1(0,2#000101010,Rs2,Rd). +%% fsqrtq(Rs2, Rd) -> fpop1(0,2#000101011,Rs2,Rd). + +fadds(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001000001,Rs2,Rd). +faddq(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001000011,Rs2,Rd). +fsubs(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001000101,Rs2,Rd). +fsubq(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001000111,Rs2,Rd). + +fmuls(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001001001,Rs2,Rd). +fmulq(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001001011,Rs2,Rd). +%% fsmuld(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001101001,Rs2,Rd). +%% fdmulq(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001101110,Rs2,Rd). +fdivs(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001001101,Rs2,Rd). +fdivq(Rs1, Rs2, Rd) -> fpop1(Rs1,2#001001111,Rs2,Rd). + +%% Uses fcc0 +%% fcmps(Rs1, Rs2) -> fpop2(Rs1,2#001010001,Rs2,0). +%% fcmpd(Rs1, Rs2) -> fpop2(Rs1,2#001010010,Rs2,0). +%% fcmpq(Rs1, Rs2) -> fpop2(Rs1,2#001010011,Rs2,0). +%% fcmpes(Rs1, Rs2) -> fpop2(Rs1,2#001010101,Rs2,0). +%% fcmped(Rs1, Rs2) -> fpop2(Rs1,2#001010110,Rs2,0). +%% fcmpeq(Rs1, Rs2) -> fpop2(Rs1,2#001010111,Rs2,0). + +%% fcmps(N, Rs1, Rs2) -> fpcn(N,2#001010001,Rs1,Rs2). +%% fcmpd(N, Rs1, Rs2) -> fpcn(N,2#001010010,Rs1,Rs2). +%% fcmpq(N, Rs1, Rs2) -> fpcn(N,2#001010011,Rs1,Rs2). +%% fcmpes(N, Rs1, Rs2) -> fpcn(N,2#001010101,Rs1,Rs2). +%% fcmped(N, Rs1, Rs2) -> fpcn(N,2#001010110,Rs1,Rs2). +%% fcmpeq(N, Rs1, Rs2) -> fpcn(N,2#001010111,Rs1,Rs2). + +stfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100100, Rs1, Offset). +stdf(Rd, Rs1, Rs2) -> format3a(2#11, Rd, 2#100111, Rs1, 0, Rs2). +stdfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100111, Rs1, Offset). +stqf(Rd, Rs1, Rs2) -> format3a(2#11, Rd, 2#100110, Rs1, 0, Rs2). +stqfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100110, Rs1, Offset). +%% stfsr(Rd, Rs1, Rs2) -> format3a(2#11, Rd, 2#100101, Rs1, 0, Rs2). +%% stfsri(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100101, Rs1, Offset). + +ldfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100000, Rs1, Offset). +lddf(Rd, Rs1, Rs2) -> format3a(2#11, Rd, 2#100011, Rs1, 0, Rs2). +lddfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100011, Rs1, Offset). +ldqf(Rd, Rs1, Rs2) -> format3a(2#11, Rd, 2#100010, Rs1, 0, Rs2). +ldqfi(Rd, Rs1, Offset) -> format3b(2#11, Rd, 2#100010, Rs1, Offset). +%% ldxfsr(Rs1, Rs2) -> format3a(2#11, 1, 2#100001, Rs1, 0, Rs2). +%% ldxfsri(Rs1, Offset) -> format3b(2#11, 1, 2#100001, Rs1, Offset). + +%% fpcn(N, Opf, Rs1, Rs2) -> +%% case N of +%% 0 -> fpc0(Opf, Rs1, Rs2); +%% 1 -> fpc1(Opf, Rs1, Rs2); +%% 2 -> fpc2(Opf, Rs1, Rs2); +%% 3 -> fpc3(Opf, Rs1, Rs2) +%% end. + +%% fpc0(Opf, Rs1, Rs2) -> format3c(2#10, 2#00000, 2#110101, Rs1, Opf, Rs2). +%% fpc1(Opf, Rs1, Rs2) -> format3c(2#10, 2#00001, 2#110101, Rs1, Opf, Rs2). +%% fpc2(Opf, Rs1, Rs2) -> format3c(2#10, 2#00010, 2#110101, Rs1, Opf, Rs2). +%% fpc3(Opf, Rs1, Rs2) -> format3c(2#10, 2#00011, 2#110101, Rs1, Opf, Rs2). +-endif. % FP insns + +%%% +%%% Main Encode Dispatch +%%% + +insn_encode(Op, Opnds) -> + case Op of + 'add' -> add(Opnds); + 'addcc' -> addcc(Opnds); + 'and' -> 'and'(Opnds); + 'andcc' -> andcc(Opnds); + 'ba' -> ba(Opnds); + 'bp' -> bp(Opnds); + 'br' -> br(Opnds); + 'call' -> call(Opnds); + 'jmpl' -> jmpl(Opnds); + 'ldsb' -> ldsb(Opnds); + 'ldsh' -> ldsh(Opnds); + 'ldsw' -> ldsw(Opnds); + 'ldub' -> ldub(Opnds); + 'lduh' -> lduh(Opnds); + 'lduw' -> lduw(Opnds); + 'ldx' -> ldx(Opnds); + 'mulx' -> mulx(Opnds); + 'or' -> 'or'(Opnds); + 'orcc' -> orcc(Opnds); + 'rd' -> rd(Opnds); + 'sethi' -> sethi(Opnds); + 'sll' -> sll(Opnds); + 'sllx' -> sllx(Opnds); + 'smul' -> smul(Opnds); + 'sra' -> sra(Opnds); + 'srax' -> srax(Opnds); + 'srl' -> srl(Opnds); + 'srlx' -> srlx(Opnds); + 'stb' -> stb(Opnds); + 'stw' -> stw(Opnds); + 'stx' -> stx(Opnds); + 'sub' -> sub(Opnds); + 'subcc' -> subcc(Opnds); + 'xor' -> 'xor'(Opnds); + 'xorcc' -> xorcc(Opnds); + 'faddd' -> faddd(Opnds); + 'fdivd' -> fdivd(Opnds); + 'fmuld' -> fmuld(Opnds); + 'fsubd' -> fsubd(Opnds); + 'fitod' -> fitod(Opnds); + 'fmovd' -> fmovd(Opnds); + 'fnegd' -> fnegd(Opnds); + 'ldf' -> ldf(Opnds); + 'stf' -> stf(Opnds); + _ -> exit({?MODULE,insn_encode,Op}) + end. + +%%% +%%% Testing Interface +%%% + +-ifdef(TESTING). + +say(OS, Str) -> + file:write(OS, Str). + +hex_digit(Dig0) -> + Dig = Dig0 band 16#F, + if Dig >= 16#A -> $A + (Dig - 16#A); + true -> $0 + Dig + end. + +say_byte(OS, Byte) -> + say(OS, [hex_digit(Byte bsr 4)]), + say(OS, [hex_digit(Byte)]). + +say_word(OS, Word) -> + say(OS, "0x"), + say_byte(OS, Word bsr 24), + say_byte(OS, Word bsr 16), + say_byte(OS, Word bsr 8), + say_byte(OS, Word). + +t(OS, Op, Opnds) -> + Word = insn_encode(Op, Opnds), + say(OS, "\t.long "), + say_word(OS, Word), + say(OS, "\n"). + +dotest1(OS) -> + say(OS, "\t.text\n\t.align 4\n"), + []. + +dotest() -> dotest1(group_leader()). + +dotest(File) -> + {ok,OS} = file:open(File, [write]), + dotest1(OS), + file:close(OS). + +-endif. |