Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example failure - AVX512F/VL intrinsic support? #33

Open
zbjornson opened this issue Jan 10, 2019 · 10 comments
Open

Example failure - AVX512F/VL intrinsic support? #33

zbjornson opened this issue Jan 10, 2019 · 10 comments

Comments

@zbjornson
Copy link

Hi folks, cool project!

I was trying out a few of my code snippets but can't seem to get them to work. Here's an example:

#include <x86intrin.h>

__m512 huge = _mm512_set1_pd(2);
__m512 tiny = _mm512_set1_pd(-2);
__m512 one = _mm512_set1_pd(1.0);

void sgm(__m512& prodv, __m512& scales, __m512 const incoming) {
	prodv = _mm512_mul_pd(prodv, incoming);
	auto pgeh = _mm512_cmp_pd_mask(prodv, huge, _CMP_GE_OQ);
	auto plet = _mm512_cmp_pd_mask(prodv, tiny, _CMP_LE_OQ);
	prodv = _mm512_mask_mul_pd(prodv, pgeh, prodv, tiny);
	prodv = _mm512_mask_mul_pd(prodv, plet, prodv, huge);
	scales = _mm512_mask_add_epi64(scales, pgeh, scales, one);
	scales = _mm512_mask_sub_epi64(scales, plet, scales, one);
}

Removing the & in the parameter list and making it return prodv gets it a bit further, but not much. All of the instructions are reported as "unsupported command".

@zbjornson
Copy link
Author

Ah, I see here that only a few commands are supported. Adding all of AVX512 I'm sure will be a beast.

@lemire
Copy link
Collaborator

lemire commented Jan 10, 2019

It may be hard to support all of AVX512 on a short time horizon.

@zbjornson
Copy link
Author

Are you manually adding each intrinsic? It would probably be worth programmatically parsing the <operation> elements in the intrinsic data from Intel (https://software.intel.com/sites/landingpage/IntrinsicsGuide/files/data-3.4.2.xml) instead.

@zbjornson
Copy link
Author

At quick glance, I'm actually not sure how this tool works. I see in src/components/ASMVisualizer.js, you have four asm ins'ns hand-coded, which would indeed be very labor-intensive to add even all of AVX or AVX2. How/where is the intrinsic translated to the instruction? Are you using the acorn JS parser for C++?

I'm interested to take a stab at an alternative approach -- something like using LLVM to get the actual assembly with optimization and whatever compiler flags, and then the operation code from Intel to create the SIMD visualization of the vector instructions programmatically. Let me know if that's of interest to you. That would also make integration with Godbolt much easier.

@lemire
Copy link
Collaborator

lemire commented Jan 10, 2019

@zbjornson That's an intriguing possibility.

The operation elements are made of pseudocode, so we would need to write a parser for this pseudocode first. Do you know if they use a standard grammar?

Then you need to map the parsed pseudocode to a graphical representation.

Hmmm...

@pmntang @piotte13

@lemire
Copy link
Collaborator

lemire commented Jan 10, 2019

At quick glance, I'm actually not sure how this tool works.

We call our technique "magic". It is only taught at the very best sorcery schools.

I see in src/components/ASMVisualizer.js, you have four asm ins'ns hand-coded, which would indeed be very labor-intensive to add even all of AVX or AVX2.

It is not that bad because a lot of instructions are going to fit into predetermined patterns. To code absolutely everything is going to be labor intensive, yes... but we think that coding many of the frequently used intrinsics ought to be fine.

How/where is the intrinsic translated to the instruction? Are you using the acorn JS parser for C++?

We tried like hell to parse C/C++ using JavaScript, but we did not manage to do it. I know, I know, it ought to be easy, right? I thought so, but apparently it is not. However you can send the C/C++ to a server, have it compile it down to assembler and then parse that.

Told you: magic.

I'm interested to take a stab at an alternative approach -- something like using LLVM to get the actual assembly with optimization and whatever compiler flags, and then the operation code from Intel to create the SIMD visualization of the vector instructions programmatically. Let me know if that's of interest to you. That would also make integration with Godbolt much easier.

We already receive the assembly.

The part that I am interested in is "SIMD visualization of the vector instructions programmatically".

At this point, we are still discussing how to do it cheaply and correctly. If you have ideas, please share.

One thing that we did not discuss is how to do turn the assembly instruction and do the corresponding computation... We want to do that in the browser, as part of the animation... and we want to make it so that the user can manipulate the data and see the effect. To this end, we are planning to go the WebAssembly route (got a prototype somewhere on GitHub).

@zbjornson
Copy link
Author

Thanks for the info.

I can take a shot at a parser for Intel's operation syntax that returns an AST. I think that will be relatively straightforward using something like PEG.js and I think will be a much faster/accurate/easier way of building this tool. Will try some evening this week or weekend.

it ought to be easy, right?

Given the size of the C++ spec, that definitely would not have been my guess. :)

Can you point me to where you request/receive the assembly please? I looked for an exec/spawn call but couldn't find one.

turn the assembly instruction and do the corresponding computation... We want to do that in the browser, as part of the animation

With the parsed operation (what I said I'll work on above), I think you could translate that AST into JS operations fairly easily... handling signalings, things that read/write MXCSR and all the rounding ops will be a potential pain point.

@lemire
Copy link
Collaborator

lemire commented Jan 10, 2019

Given the size of the C++ spec

The C spec is smaller... but even just supporting a limited subset proved to be a headache.

I looked for an exec/spawn call but couldn't find one.

The assembly is requested via a REST call... Were you expecting us to launch a compiler from the browser? :-) I think most people don't have a compiler along with their browser.

I think you could translate that AST into JS operations fairly easily... handling signalings, things that read/write MXCSR and all the rounding ops will be a potential pain point.

The flags are the least of our worries... JavaScript does not support unsigned ints, 32-bit floats, 64-bit ints... to say nothing of converting between those. This can all be done in JavaScript, but it risks becoming a giant wall of code, especially if you add the necessary testing. My current proposal is to represent all values as hexadecimal strings, and push them to a separate WebAssembly library for processing...

https://github.com/lemire/jstypes

But the computation itself is a relatively modest problem compared to the visualization.

This being said, I do think that your approach has potentially great merit compared with our current struggle to scale this up.

@zbjornson
Copy link
Author

The assembly is requested via a REST call

I see now it goes to the godbolt API; I was expecting the compiler to be run by this module's server.


I have a grammar mostly done (I have two more expression types to add). Two examples below, including a behemoth from AVX-512.

_mm_shuffle_pd
{ type: 'Program',
  body:
   [ { type: 'ExpressionStatement',
       expression:
        { type: 'AssignmentExpression',
          operator: ':=',
          left:
           { type: 'MemberExpression',
             object: { type: 'Identifier', name: 'dst' },
             range:
              { start: { type: 'Literal', value: 63 },
                end: { type: 'Literal', value: 0 } },
             computed: true },
          right:
           { type: 'ConditionalExpression',
             test:
              { type: 'BinaryExpression',
                operator: '==',
                left:
                 { type: 'MemberExpression',
                   object: { type: 'Identifier', name: 'imm8' },
                   property: { type: 'Literal', value: 0 },
                   computed: true },
                right: { type: 'Literal', value: 0 } },
             consequent:
              { type: 'MemberExpression',
                object: { type: 'Identifier', name: 'a' },
                range:
                 { start: { type: 'Literal', value: 63 },
                   end: { type: 'Literal', value: 0 } },
                computed: true },
             alternate:
              { type: 'MemberExpression',
                object: { type: 'Identifier', name: 'a' },
                range:
                 { start: { type: 'Literal', value: 127 },
                   end: { type: 'Literal', value: 64 } },
                computed: true } } } },
     { type: 'ExpressionStatement',
       expression:
        { type: 'AssignmentExpression',
          operator: ':=',
          left:
           { type: 'MemberExpression',
             object: { type: 'Identifier', name: 'dst' },
             range:
              { start: { type: 'Literal', value: 127 },
                end: { type: 'Literal', value: 64 } },
             computed: true },
          right:
           { type: 'ConditionalExpression',
             test:
              { type: 'BinaryExpression',
                operator: '==',
                left:
                 { type: 'MemberExpression',
                   object: { type: 'Identifier', name: 'imm8' },
                   property: { type: 'Literal', value: 1 },
                   computed: true },
                right: { type: 'Literal', value: 0 } },
             consequent:
              { type: 'MemberExpression',
                object: { type: 'Identifier', name: 'b' },
                range:
                 { start: { type: 'Literal', value: 63 },
                   end: { type: 'Literal', value: 0 } },
                computed: true },
             alternate:
              { type: 'MemberExpression',
                object: { type: 'Identifier', name: 'b' },
                range:
                 { start: { type: 'Literal', value: 127 },
                   end: { type: 'Literal', value: 64 } },
                computed: true } } } } ] }
_mm_mask_fixupimm_sd
{ type: 'Program',
  body:
   [ { type: 'Enum',
       id: { type: 'Identifier', name: 'TOKEN_TYPE' },
       values:
        [ { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'QNAN_TOKEN' },
            enumValue: { type: 'Literal', value: 0 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'SNAN_TOKEN' },
            enumValue: { type: 'Literal', value: 1 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'ZERO_VALUE_TOKEN' },
            enumValue: { type: 'Literal', value: 2 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'ONE_VALUE_TOKEN' },
            enumValue: { type: 'Literal', value: 3 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'NEG_INF_TOKEN' },
            enumValue: { type: 'Literal', value: 4 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'POS_INF_TOKEN' },
            enumValue: { type: 'Literal', value: 5 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'NEG_VALUE_TOKEN' },
            enumValue: { type: 'Literal', value: 6 } },
          { type: 'EnumMember',
            propName: { type: 'Identifier', name: 'POS_VALUE_TOKEN' },
            enumValue: { type: 'Literal', value: 7 } } ] },
     { type: 'FunctionDeclaration',
       id: { type: 'Identifier', name: 'FIXUPIMMPD' },
       params:
        [ { type: 'Parameter',
            name: { type: 'Identifier', name: 'src1' },
            range:
             { start: { type: 'Literal', value: 63 },
               end: { type: 'Literal', value: 0 } } },
          { type: 'Parameter',
            name: { type: 'Identifier', name: 'src2' },
            range:
             { start: { type: 'Literal', value: 63 },
               end: { type: 'Literal', value: 0 } } },
          { type: 'Parameter',
            name: { type: 'Identifier', name: 'src3' },
            range:
             { start: { type: 'Literal', value: 63 },
               end: { type: 'Literal', value: 0 } } },
          { type: 'Parameter',
            name: { type: 'Identifier', name: 'imm8' },
            range:
             { start: { type: 'Literal', value: 7 },
               end: { type: 'Literal', value: 0 } } } ],
       body:
        { type: 'BlockStatement',
          body:
           [ { type: 'ExpressionStatement',
               expression:
                { type: 'AssignmentExpression',
                  operator: ':=',
                  left:
                   { type: 'MemberExpression',
                     object: { type: 'Identifier', name: 'tsrc' },
                     range:
                      { start: { type: 'Literal', value: 63 },
                        end: { type: 'Literal', value: 0 } },
                     computed: true },
                  right:
                   { type: 'ConditionalExpression',
                     test:
                      { type: 'BinaryExpression',
                        operator: [ 'AND', undefined ],
                        left:
                         { type: 'BinaryExpression',
                           operator: '==',
                           left:
                            { type: 'MemberExpression',
                              object: { type: 'Identifier', name: 'src2' },
                              range:
                               { start: { type: 'Literal', value: 62 },
                                 end: { type: 'Literal', value: 52 } },
                              computed: true },
                           right: { type: 'Literal', value: 0 } },
                        right:
                         { type: 'BinaryExpression',
                           operator: '==',
                           left:
                            { type: 'MemberExpression',
                              object: { type: 'Identifier', name: 'MXCSR' },
                              property: { type: 'Identifier', name: 'DAZ' },
                              computed: false },
                           right: { type: 'Literal', value: 1 } } },
                     consequent: { type: 'Literal', value: 0 },
                     alternate:
                      { type: 'MemberExpression',
                        object: { type: 'Identifier', name: 'src2' },
                        range:
                         { start: { type: 'Literal', value: 63 },
                           end: { type: 'Literal', value: 0 } },
                        computed: true } } } },
             { type: 'CaseStatement',
               discriminant:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'tsrc' },
                  range:
                   { start: { type: 'Literal', value: 63 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true },
               cases:
                [ { type: 'Case',
                    test: { type: 'Identifier', name: 'QNAN_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 0 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'SNAN_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 1 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'ZERO_VALUE_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 2 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'ONE_VALUE_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 3 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'NEG_INF_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 4 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'POS_INF_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 5 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'NEG_VALUE_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 6 } } } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'POS_VALUE_TOKEN' },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left: { type: 'Identifier', name: 'j' },
                          right: { type: 'Literal', value: 7 } } } } ] },
             { type: 'ExpressionStatement',
               expression:
                { type: 'AssignmentExpression',
                  operator: ':=',
                  left:
                   { type: 'MemberExpression',
                     object: { type: 'Identifier', name: 'token_response' },
                     range:
                      { start: { type: 'Literal', value: 3 },
                        end: { type: 'Literal', value: 0 } },
                     computed: true },
                  right:
                   { type: 'MemberExpression',
                     object: { type: 'Identifier', name: 'src3' },
                     range:
                      { start:
                         { type: 'BinaryExpression',
                           operator: '+',
                           left: { type: 'Literal', value: 3 },
                           right:
                            { type: 'BinaryExpression',
                              operator: '*',
                              left: { type: 'Literal', value: 4 },
                              right: { type: 'Identifier', name: 'j' } } },
                        end:
                         { type: 'BinaryExpression',
                           operator: '*',
                           left: { type: 'Literal', value: 4 },
                           right: { type: 'Identifier', name: 'j' } } },
                     computed: true } } },
             { type: 'CaseStatement',
               discriminant:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'token_response' },
                  range:
                   { start: { type: 'Literal', value: 3 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true },
               cases:
                [ { type: 'Case',
                    test: { type: 'Literal', value: 0 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'src1' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 1 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'tsrc' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 2 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'CallExpression',
                             callee: { type: 'Identifier', name: 'QNaN' },
                             arguments:
                              [ { type: 'MemberExpression',
                                  object: { type: 'Identifier', name: 'tsrc' },
                                  range:
                                   { start: { type: 'Literal', value: 63 },
                                     end: { type: 'Literal', value: 0 } },
                                  computed: true } ] } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 3 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right: { type: 'Identifier', name: 'QNAN_Indefinite' } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 4 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '-',
                             argument: { type: 'Identifier', name: 'INF' },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 5 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '+',
                             argument: { type: 'Identifier', name: 'INF' },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 6 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'ConditionalExpression',
                             test:
                              { type: 'MemberExpression',
                                object: { type: 'Identifier', name: 'tsrc' },
                                property: { type: 'Identifier', name: 'sign' },
                                computed: false },
                             consequent:
                              { type: 'UnaryExpression',
                                operator: '-',
                                argument: { type: 'Identifier', name: 'INF' },
                                prefix: true },
                             alternate:
                              { type: 'UnaryExpression',
                                operator: '+',
                                argument: { type: 'Identifier', name: 'INF' },
                                prefix: true } } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 7 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '-',
                             argument: { type: 'Literal', value: 0 },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 8 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '+',
                             argument: { type: 'Literal', value: 0 },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 9 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '-',
                             argument: { type: 'Literal', value: 1 },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 10 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '+',
                             argument: { type: 'Literal', value: 1 },
                             prefix: true } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 11 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'BinaryExpression',
                             operator: '/',
                             left: { type: 'Literal', value: 1 },
                             right: { type: 'Literal', value: 2 } } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 12 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right: { type: 'Literal', value: 90 } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 13 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'BinaryExpression',
                             operator: '/',
                             left: { type: 'Identifier', name: 'PI' },
                             right: { type: 'Literal', value: 2 } } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 14 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right: { type: 'Identifier', name: 'MAX_FLOAT' } } } },
                  { type: 'Case',
                    test: { type: 'Literal', value: 15 },
                    consequent:
                     { type: 'ExpressionStatement',
                       expression:
                        { type: 'AssignmentExpression',
                          operator: ':=',
                          left:
                           { type: 'MemberExpression',
                             object: { type: 'Identifier', name: 'dest' },
                             range:
                              { start: { type: 'Literal', value: 63 },
                                end: { type: 'Literal', value: 0 } },
                             computed: true },
                          right:
                           { type: 'UnaryExpression',
                             operator: '-',
                             argument: { type: 'Identifier', name: 'MAX_FLOAT' },
                             prefix: true } } } } ] },
             { type: 'CaseStatement',
               discriminant:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'tsrc' },
                  range:
                   { start: { type: 'Literal', value: 31 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true },
               cases:
                [ { type: 'Case',
                    test: { type: 'Identifier', name: 'ZERO_VALUE_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 0 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'ZE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'ZERO_VALUE_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 1 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'ONE_VALUE_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 2 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'ZE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'ONE_VALUE_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 3 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'SNAN_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 4 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'NEG_INF_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 5 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'NEG_VALUE_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 6 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } },
                  { type: 'Case',
                    test: { type: 'Identifier', name: 'POS_INF_TOKEN' },
                    consequent:
                     { type: 'IfStatement',
                       test:
                        { type: 'MemberExpression',
                          object: { type: 'Identifier', name: 'imm8' },
                          property: { type: 'Literal', value: 7 },
                          computed: true },
                       consequent:
                        { type: 'ExpressionStatement',
                          expression:
                           { type: 'SetExpression',
                             flag: { type: 'Identifier', name: 'IE' } } },
                       alternate: null } } ] },
             { type: 'ReturnStatement',
               argument:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'dest' },
                  range:
                   { start: { type: 'Literal', value: 63 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true } } ] } },
     { type: 'IfStatement',
       test:
        { type: 'MemberExpression',
          object: { type: 'Identifier', name: 'k' },
          property: { type: 'Literal', value: 0 },
          computed: true },
       consequent:
        [ { type: 'ExpressionStatement',
            expression:
             { type: 'AssignmentExpression',
               operator: ':=',
               left:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'dst' },
                  range:
                   { start: { type: 'Literal', value: 63 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true },
               right:
                { type: 'CallExpression',
                  callee: { type: 'Identifier', name: 'FIXUPIMMPD' },
                  arguments:
                   [ { type: 'MemberExpression',
                       object: { type: 'Identifier', name: 'a' },
                       range:
                        { start: { type: 'Literal', value: 63 },
                          end: { type: 'Literal', value: 0 } },
                       computed: true },
                     { type: 'MemberExpression',
                       object: { type: 'Identifier', name: 'b' },
                       range:
                        { start: { type: 'Literal', value: 63 },
                          end: { type: 'Literal', value: 0 } },
                       computed: true },
                     { type: 'MemberExpression',
                       object: { type: 'Identifier', name: 'c' },
                       range:
                        { start: { type: 'Literal', value: 63 },
                          end: { type: 'Literal', value: 0 } },
                       computed: true },
                     { type: 'MemberExpression',
                       object: { type: 'Identifier', name: 'imm8' },
                       range:
                        { start: { type: 'Literal', value: 7 },
                          end: { type: 'Literal', value: 0 } },
                       computed: true } ] } } } ],
       alternate:
        [ { type: 'ExpressionStatement',
            expression:
             { type: 'AssignmentExpression',
               operator: ':=',
               left:
                { type: 'MemberExpression',
                  object: { type: 'Identifier', name: 'dst' },
                  range:
                   { start: { type: 'Literal', value: 63 },
                     end: { type: 'Literal', value: 0 } },
                  computed: true },
               right: { type: 'Literal', value: 0 } } } ] },
     { type: 'ExpressionStatement',
       expression:
        { type: 'AssignmentExpression',
          operator: ':=',
          left:
           { type: 'MemberExpression',
             object: { type: 'Identifier', name: 'dst' },
             range:
              { start: { type: 'Literal', value: 127 },
                end: { type: 'Literal', value: 64 } },
             computed: true },
          right:
           { type: 'MemberExpression',
             object: { type: 'Identifier', name: 'a' },
             range:
              { start: { type: 'Literal', value: 127 },
                end: { type: 'Literal', value: 64 } },
             computed: true } } },
     { type: 'ExpressionStatement',
       expression:
        { type: 'AssignmentExpression',
          operator: ':=',
          left:
           { type: 'MemberExpression',
             object: { type: 'Identifier', name: 'dst' },
             range:
              { start: { type: 'Identifier', name: 'MAX' },
                end: { type: 'Literal', value: 128 } },
             computed: true },
          right: { type: 'Literal', value: 0 } } } ] }

I'm not entirely positive that this will ultimately be useful, but it'll be available.


turn the assembly instruction and do the corresponding computation... We want to do that in the browser, as part of the animation

Have you considered recording the process executed on a real processor and just replaying it in the browser? See [1-4]. I'm not sure if it's possible to record on AWS since most perf counters are locked down, but that would eliminate the need to emulate in JS.

[1] https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing
[2] https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html
[3] https://rr-project.org/
[4] https://github.com/01org/processor-trace

@lemire
Copy link
Collaborator

lemire commented Jan 14, 2019

Looking forward to your grammar.

Have you considered recording the process executed on a real processor and just replaying it in the browser?

It is certainly is possible to run the function through a debugger. You can control lldb via Python. Visual Studio has a great C++ debugger.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants