diff options
author | aph <none@none> | 2012-07-06 14:46:36 +0100 |
---|---|---|
committer | aph <none@none> | 2012-07-06 14:46:36 +0100 |
commit | 60bd673086dc76432c7cd5221a22115296d08428 (patch) | |
tree | ce4f48a1be97ee0c7b863d3efe445bd587beb88c | |
parent | ef0c1cab6b61fe7ef8d50b259cdb09a7475296b6 (diff) |
Floating-point instructions
-rw-r--r-- | src/cpu/aarch64/vm/assembler_aarch64.cpp | 113 | ||||
-rw-r--r-- | src/cpu/aarch64/vm/assembler_aarch64.hpp | 214 | ||||
-rw-r--r-- | src/cpu/aarch64/vm/register_aarch64.hpp | 77 |
3 files changed, 397 insertions, 7 deletions
diff --git a/src/cpu/aarch64/vm/assembler_aarch64.cpp b/src/cpu/aarch64/vm/assembler_aarch64.cpp index f8b693d8c..0e5b72f8b 100644 --- a/src/cpu/aarch64/vm/assembler_aarch64.cpp +++ b/src/cpu/aarch64/vm/assembler_aarch64.cpp @@ -179,6 +179,8 @@ void entry(CodeBuffer *cb) { __ ldrw(r8, entry); __ ldr(r8, entry); + __ ldrs(F12, entry); + __ ldrd(F12, entry); __ ldrsw(r8, entry); __ prfm(0b10000, __ pc() + 8); @@ -261,6 +263,26 @@ void entry(CodeBuffer *cb) { __ ldrsb(r3, Address_aarch64(__ pre(r4, 8))); __ ldrsb(r3, Address_aarch64(__ post(r4, 8))); + __ prfm(r3, Address_aarch64(r4)); + __ prfm(r3, Address_aarch64(r4, 8)); + __ prfm(r3, Address_aarch64(r4, r6)); + __ prfm(r3, Address_aarch64(__ pre(r4, 8))); + __ prfm(r3, Address_aarch64(__ post(r4, 8))); + +#define INSN(NAME, size, op) \ + __ NAME(F7, Address_aarch64(r4)); \ + __ NAME(F7, Address_aarch64(r4, 8)); \ + __ NAME(F7, Address_aarch64(r4, r6)); \ + __ NAME(F7, Address_aarch64(__ pre(r4, 8))); \ + __ NAME(F7, Address_aarch64(__ post(r4, 8))); + + INSN(strd, 0b11, 0b00); + INSN(strs, 0b10, 0b00); + INSN(ldrd, 0b11, 0b01); + INSN(ldrs, 0b10, 0b01); + +#undef INSN + __ eorw (r19, r7, r11, __ lsl, 3); __ bic(r27, r3, r1, __ ror, 22); @@ -346,6 +368,97 @@ void entry(CodeBuffer *cb) { __ ldr(r3, Address_aarch64(r2, 12)); __ ldr(r3, Address_aarch64(r2, -12)); +#define INSN(NAME, op31, type, opcode) \ + __ NAME(F0, F1); + + INSN(fmovs, 0b000, 0b00, 0b000000); + INSN(fabss, 0b000, 0b00, 0b000001); + INSN(fnegs, 0b000, 0b00, 0b000010); + INSN(fsqrts, 0b000, 0b00, 0b000011); + INSN(fcvts, 0b000, 0b00, 0b000101); + + INSN(fmovd, 0b000, 0b01, 0b000000); + INSN(fabsd, 0b000, 0b01, 0b000001); + INSN(fnegd, 0b000, 0b01, 0b000010); + INSN(fsqrtd, 0b000, 0b01, 0b000011); + INSN(fcvtd, 0b000, 0b01, 0b000100); + +#undef INSN + +#define INSN(NAME, op31, type, opcode) \ + __ NAME(F0, F1, F1); + + INSN(fmuls, 0b000, 0b00, 0b0000); + INSN(fdivs, 0b000, 0b00, 0b0001); + INSN(fadds, 0b000, 0b00, 0b0010); + INSN(fsubs, 0b000, 0b00, 0b0011); + INSN(fnmuls, 0b000, 0b00, 0b1000); + + INSN(fmuls, 0b000, 0b01, 0b0000); + INSN(fdivs, 0b000, 0b01, 0b0001); + INSN(fadds, 0b000, 0b01, 0b0010); + INSN(fsubs, 0b000, 0b01, 0b0011); + INSN(fnmuls, 0b000, 0b01, 0b1000); + +#undef INSN + +#define INSN(NAME, op31, type, o1, o0) \ + __ NAME(F0, F1, F2, F3); + + INSN(fmadds, 0b000, 0b00, 0, 0); + INSN(fmsubs, 0b000, 0b00, 0, 1); + INSN(fnmadds, 0b000, 0b00, 0, 0); + INSN(fnmsubs, 0b000, 0b00, 0, 1); + + INSN(fmadd, 0b000, 0b01, 0, 0); + INSN(fmsubd, 0b000, 0b01, 0, 1); + INSN(fnmadd, 0b000, 0b01, 0, 0); + INSN(fnmsub, 0b000, 0b01, 0, 1); + +#undef INSN + +#define INSN(NAME, op31, type, rmode, opcode) \ + __ NAME(r1, F0); + + INSN(fcvtszw, 0b000, 0b00, 0b11, 0b000); + INSN(fcvtzs, 0b000, 0b01, 0b11, 0b000); + INSN(fcvtzdw, 0b100, 0b00, 0b11, 0b000); + INSN(fcvtszd, 0b100, 0b01, 0b11, 0b000); + + INSN(fmovs, 0b000, 0b00, 0b00, 0b110); + INSN(fmovd, 0b100, 0b01, 0b00, 0b111); + + INSN(fmovhid, 0b100, 0b10, 0b01, 0b110); + +#undef INSN + +#define INSN(NAME, op31, type, rmode, opcode) \ + __ NAME(F2, r3); + + INSN(fmovs, 0b000, 0b00, 0b00, 0b111); + INSN(fmovd, 0b100, 0b01, 0b00, 0b111); + + INSN(fmovhid, 0b100, 0b10, 0b01, 0b110); + +#undef INSN + +#define INSN(NAME, op31, type, op, opcode2) \ + __ NAME(F0, F1); +#define INSN1(NAME, op31, type, op, opcode2) \ + __ NAME(F1); + + INSN(fcmps, 0b000, 0b00, 0b00, 0b00000); + INSN1(fcmps, 0b000, 0b00, 0b00, 0b01000); + INSN(fcmpes, 0b000, 0b00, 0b00, 0b10000); + INSN1(fcmpes, 0b000, 0b00, 0b00, 0b11000); + + INSN(fcmpd, 0b000, 0b01, 0b00, 0b00000); + INSN1(fcmpd, 0b000, 0b01, 0b00, 0b01000); + INSN(fcmped, 0b000, 0b01, 0b00, 0b10000); + INSN1(fcmped, 0b000, 0b01, 0b00, 0b11000); + +#undef INSN + Disassembler::decode(entry, __ pc()); diff --git a/src/cpu/aarch64/vm/assembler_aarch64.hpp b/src/cpu/aarch64/vm/assembler_aarch64.hpp index dcd68d7fa..064b9b507 100644 --- a/src/cpu/aarch64/vm/assembler_aarch64.hpp +++ b/src/cpu/aarch64/vm/assembler_aarch64.hpp @@ -97,6 +97,10 @@ public: f(r->encoding_nocheck(), lsb + 4, lsb); } + void rf(FloatRegister r, int lsb) { + f(r->encoding_nocheck(), lsb + 4, lsb); + } + unsigned get(int msb = 31, int lsb = 0) { int nbits = msb - lsb + 1; unsigned mask = ((1U << nbits) - 1) << lsb; @@ -237,6 +241,9 @@ public: void rf(Register reg, int lsb) { current->rf(reg, lsb); } + void rf(FloatRegister reg, int lsb) { + current->rf(reg, lsb); + } void fixed(unsigned value, unsigned mask) { current->fixed(value, mask); } @@ -598,6 +605,20 @@ public: #undef INSN #define INSN(NAME, opc, V) \ + void NAME(FloatRegister Rt, address dest) { \ + long offset = (dest - pc()) >> 2; \ + starti; \ + f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ + sf(offset, 23, 5); \ + rf((Register)Rt, 0); \ + } + + INSN(ldrs, 0b00, 1); + INSN(ldrd, 0b01, 1); + +#undef INSN + +#define INSN(NAME, opc, V) \ void NAME(int prfop, address dest) { \ long offset = (dest - pc()) >> 2; \ starti; \ @@ -658,19 +679,19 @@ public: #undef INSN // Load/store register (all modes) - void ld_st2(Register Rt, Address_aarch64 adr, int size, int op) { + void ld_st2(Register Rt, Address_aarch64 adr, int size, int op, int V = 0) { starti; f(size, 31, 30); f(op, 23, 22); // str - f(0, 26); // general reg + f(V, 26); // general reg? rf(Rt, 0); adr.encode(current); } -#define INSN(NAME, size, op) \ - void NAME(Register Rt, Address_aarch64 adr) { \ - ld_st2(Rt, adr, size, op); \ - } +#define INSN(NAME, size, op) \ + void NAME(Register Rt, Address_aarch64 adr) { \ + ld_st2(Rt, adr, size, op); \ + } \ INSN(str, 0b11, 0b00); INSN(strw, 0b10, 0b00); @@ -687,6 +708,22 @@ public: INSN(ldrshw, 0b01, 0b10); INSN(ldrsw, 0b10, 0b10); + INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with + // writeback modes, but the assembler + // doesn't enfore that. + +#undef INSN + +#define INSN(NAME, size, op) \ + void NAME(FloatRegister Rt, Address_aarch64 adr) { \ + ld_st2((Register)Rt, adr, size, op, 1); \ + } + + INSN(strd, 0b11, 0b00); + INSN(strs, 0b10, 0b00); + INSN(ldrd, 0b11, 0b01); + INSN(ldrs, 0b10, 0b01); + #undef INSN enum shift_kind { lsl, lsr, asr, ror }; @@ -955,6 +992,171 @@ public: INSN(smulh, 0b100, 0b010, 0); INSN(umulh, 0b100, 0b110, 0); +#undef INSN + + // Floating-point data-processing (1 source) + void data_processing(unsigned op31, unsigned type, unsigned opcode, + FloatRegister Vd, FloatRegister Vn) { + starti; + f(op31, 31, 29); + f(0b11110, 28, 24); + f(type, 23, 22), f(1, 21), f(opcode, 20, 15), f(0b10000, 14, 10); + rf(Vn, 5), rf(Vd, 0); + } + +#define INSN(NAME, op31, type, opcode) \ + void NAME(FloatRegister Vd, FloatRegister Vn) { \ + data_processing(op31, type, opcode, Vd, Vn); \ + } + + INSN(fmovs, 0b000, 0b00, 0b000000); + INSN(fabss, 0b000, 0b00, 0b000001); + INSN(fnegs, 0b000, 0b00, 0b000010); + INSN(fsqrts, 0b000, 0b00, 0b000011); + INSN(fcvts, 0b000, 0b00, 0b000101); + + INSN(fmovd, 0b000, 0b01, 0b000000); + INSN(fabsd, 0b000, 0b01, 0b000001); + INSN(fnegd, 0b000, 0b01, 0b000010); + INSN(fsqrtd, 0b000, 0b01, 0b000011); + INSN(fcvtd, 0b000, 0b01, 0b000100); + +#undef INSN + + // Floating-point data-processing (2 source) + void data_processing(unsigned op31, unsigned type, unsigned opcode, + FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { + starti; + f(op31, 31, 29); + f(0b11110, 28, 24); + f(type, 23, 22), f(1, 21), f(opcode, 15, 12), f(0b10, 11, 10); + rf(Vm, 16), rf(Vn, 5), rf(Vd, 0); + } + +#define INSN(NAME, op31, type, opcode) \ + void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \ + data_processing(op31, type, opcode, Vd, Vn, Vm); \ + } + + INSN(fmuls, 0b000, 0b00, 0b0000); + INSN(fdivs, 0b000, 0b00, 0b0001); + INSN(fadds, 0b000, 0b00, 0b0010); + INSN(fsubs, 0b000, 0b00, 0b0011); + INSN(fnmuls, 0b000, 0b00, 0b1000); + + INSN(fmuld, 0b000, 0b01, 0b0000); + INSN(fdivd, 0b000, 0b01, 0b0001); + INSN(faddd, 0b000, 0b01, 0b0010); + INSN(fsubd, 0b000, 0b01, 0b0011); + INSN(fnmuld, 0b000, 0b01, 0b1000); + +#undef INSN + + // Floating-point data-processing (3 source) + void data_processing(unsigned op31, unsigned type, unsigned o1, unsigned o0, + FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, + FloatRegister Va) { + starti; + f(op31, 31, 29); + f(0b11111, 28, 24); + f(type, 23, 22), f(o1, 21), f(o1, 15); + rf(Vm, 16), rf(Vn, 10), rf(Vn, 5), rf(Vd, 0); + } + +#define INSN(NAME, op31, type, o1, o0) \ + void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, \ + FloatRegister Va) { \ + data_processing(op31, type, o1, o0, Vd, Vn, Vm, Va); \ + } + + INSN(fmadds, 0b000, 0b00, 0, 0); + INSN(fmsubs, 0b000, 0b00, 0, 1); + INSN(fnmadds, 0b000, 0b00, 0, 0); + INSN(fnmsubs, 0b000, 0b00, 0, 1); + + INSN(fmadd, 0b000, 0b01, 0, 0); + INSN(fmsubd, 0b000, 0b01, 0, 1); + INSN(fnmadd, 0b000, 0b01, 0, 0); + INSN(fnmsub, 0b000, 0b01, 0, 1); + +#undef INSN + + // Floating-point<->integer conversions + void float_int_convert(unsigned op31, unsigned type, + unsigned rmode, unsigned opcode, + Register Rd, Register Rn) { + starti; + f(op31, 31, 29); + f(0b11110, 28, 24); + f(type, 23, 22), f(1, 21), f(rmode, 20, 19); + f(opcode, 18, 16), f(0b000000, 15, 10); + rf(Rn, 5), rf(Rd, 0); + } + +#define INSN(NAME, op31, type, rmode, opcode) \ + void NAME(Register Rd, FloatRegister Vn) { \ + float_int_convert(op31, type, rmode, opcode, Rd, (Register)Vn); \ + } + + INSN(fcvtszw, 0b000, 0b00, 0b11, 0b000); + INSN(fcvtzs, 0b000, 0b01, 0b11, 0b000); + INSN(fcvtzdw, 0b100, 0b00, 0b11, 0b000); + INSN(fcvtszd, 0b100, 0b01, 0b11, 0b000); + + INSN(fmovs, 0b000, 0b00, 0b00, 0b110); + INSN(fmovd, 0b100, 0b01, 0b00, 0b110); + + INSN(fmovhid, 0b100, 0b10, 0b01, 0b110); + +#undef INSN + +#define INSN(NAME, op31, type, rmode, opcode) \ + void NAME(FloatRegister Vd, Register Rn) { \ + float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn); \ + } + + INSN(fmovs, 0b000, 0b00, 0b00, 0b111); + INSN(fmovd, 0b100, 0b01, 0b00, 0b111); + + INSN(fmovhid, 0b100, 0b10, 0b01, 0b111); + +#undef INSN + + // Floating-point compare + void float_compare(unsigned op31, unsigned type, + unsigned op, unsigned op2, + FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) { + starti; + f(op31, 31, 29); + f(0b11110, 28, 24); + f(type, 23, 22), f(1, 21); + f(op, 15, 14), f(0b1000, 13, 10), f(op2, 4, 0); + rf(Vn, 5), rf(Vm, 16); + } + + +#define INSN(NAME, op31, type, op, op2) \ + void NAME(FloatRegister Vn, FloatRegister Vm) { \ + float_compare(op31, type, op, op2, Vn, Vm); \ + } + +#define INSN1(NAME, op31, type, op, op2) \ + void NAME(FloatRegister Vn) { \ + float_compare(op31, type, op, op2, Vn); \ + } + + INSN(fcmps, 0b000, 0b00, 0b00, 0b00000); + INSN1(fcmps, 0b000, 0b00, 0b00, 0b01000); + INSN(fcmpes, 0b000, 0b00, 0b00, 0b10000); + INSN1(fcmpes, 0b000, 0b00, 0b00, 0b11000); + + INSN(fcmpd, 0b000, 0b01, 0b00, 0b00000); + INSN1(fcmpd, 0b000, 0b01, 0b00, 0b01000); + INSN(fcmped, 0b000, 0b01, 0b00, 0b10000); + INSN1(fcmped, 0b000, 0b01, 0b00, 0b11000); + +#undef INSN +#undef INSN1 Assembler_aarch64(CodeBuffer* code) : AbstractAssembler(code) { } diff --git a/src/cpu/aarch64/vm/register_aarch64.hpp b/src/cpu/aarch64/vm/register_aarch64.hpp index 24677abc9..bf9dd61c2 100644 --- a/src/cpu/aarch64/vm/register_aarch64.hpp +++ b/src/cpu/aarch64/vm/register_aarch64.hpp @@ -128,11 +128,85 @@ class FloatRegisterImpl: public AbstractRegisterImpl { // accessors int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; } + int encoding_nocheck() const { return (intptr_t)this; } bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; } const char* name() const; }; +// The float registers of the AARCH64 architecture + +CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1)); + +CONSTANT_REGISTER_DECLARATION(FloatRegister, F0 , ( 0)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F1 , ( 1)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F2 , ( 2)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F3 , ( 3)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F4 , ( 4)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F5 , ( 5)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F6 , ( 6)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F7 , ( 7)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F8 , ( 8)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F9 , ( 9)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F10 , (10)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F11 , (11)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F12 , (12)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F13 , (13)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F14 , (14)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F15 , (15)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F16 , (16)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F17 , (17)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F18 , (18)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F19 , (19)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F20 , (20)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F21 , (21)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F22 , (22)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F23 , (23)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F24 , (24)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F25 , (25)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F26 , (26)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F27 , (27)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F28 , (28)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F29 , (29)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F30 , (30)); +CONSTANT_REGISTER_DECLARATION(FloatRegister, F31 , (31)); + +#ifndef DONT_USE_REGISTER_DEFINES +#define fnoreg ((FloatRegister)(fnoreg_FloatRegisterEnumValue)) +#define F0 ((FloatRegister)( F0_FloatRegisterEnumValue)) +#define F1 ((FloatRegister)( F1_FloatRegisterEnumValue)) +#define F2 ((FloatRegister)( F2_FloatRegisterEnumValue)) +#define F3 ((FloatRegister)( F3_FloatRegisterEnumValue)) +#define F4 ((FloatRegister)( F4_FloatRegisterEnumValue)) +#define F5 ((FloatRegister)( F5_FloatRegisterEnumValue)) +#define F6 ((FloatRegister)( F6_FloatRegisterEnumValue)) +#define F7 ((FloatRegister)( F7_FloatRegisterEnumValue)) +#define F8 ((FloatRegister)( F8_FloatRegisterEnumValue)) +#define F9 ((FloatRegister)( F9_FloatRegisterEnumValue)) +#define F10 ((FloatRegister)( F10_FloatRegisterEnumValue)) +#define F11 ((FloatRegister)( F11_FloatRegisterEnumValue)) +#define F12 ((FloatRegister)( F12_FloatRegisterEnumValue)) +#define F13 ((FloatRegister)( F13_FloatRegisterEnumValue)) +#define F14 ((FloatRegister)( F14_FloatRegisterEnumValue)) +#define F15 ((FloatRegister)( F15_FloatRegisterEnumValue)) +#define F16 ((FloatRegister)( F16_FloatRegisterEnumValue)) +#define F17 ((FloatRegister)( F17_FloatRegisterEnumValue)) +#define F18 ((FloatRegister)( F18_FloatRegisterEnumValue)) +#define F19 ((FloatRegister)( F19_FloatRegisterEnumValue)) +#define F20 ((FloatRegister)( F20_FloatRegisterEnumValue)) +#define F21 ((FloatRegister)( F21_FloatRegisterEnumValue)) +#define F22 ((FloatRegister)( F22_FloatRegisterEnumValue)) +#define F23 ((FloatRegister)( F23_FloatRegisterEnumValue)) +#define F24 ((FloatRegister)( F24_FloatRegisterEnumValue)) +#define F25 ((FloatRegister)( F25_FloatRegisterEnumValue)) +#define F26 ((FloatRegister)( F26_FloatRegisterEnumValue)) +#define F27 ((FloatRegister)( F27_FloatRegisterEnumValue)) +#define F28 ((FloatRegister)( F28_FloatRegisterEnumValue)) +#define F29 ((FloatRegister)( F29_FloatRegisterEnumValue)) +#define F30 ((FloatRegister)( F30_FloatRegisterEnumValue)) +#define F31 ((FloatRegister)( F31_FloatRegisterEnumValue)) +#endif // DONT_USE_REGISTER_DEFINES + // Need to know the total number of registers of all sorts for SharedInfo. // Define a class that exports it. class ConcreteRegisterImpl : public AbstractRegisterImpl { @@ -144,7 +218,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { // it's optoregs. number_of_registers = RegisterImpl::number_of_registers + - 1 // eflags + FloatRegisterImpl::number_of_registers + + 1 // flags }; }; |