b43-asm: Add 3 new virtual instructions.
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Hi Michael,
I added three new (virtual) instructions to make the code more readable. These are "human-friendly" versions of orx, jzx and jnzx, e.g., one can use "orxh" like
orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2
instead of
orx 0, 8, r1, r2, r2
or better write
#define NEED_ACK 0x10
#define NEED_BEACON 0x20 orxh NEED_ACK, r1 & ~(NEED_ACK|NEED_BEACON), r2
instead of
orx 1, 4, 0x1, r1, r2
Similarly:
jzxh (r12 << 16 | r13) & 0x1F000, label
instead of
jzx 4, 12, r13, r12, label
Examples added to test.asm and README.
Regards,
-Francesco
-------------=--------------
The following changes are made to b43-tools
1) b43-asm assembles new virtual instructions orxh, jzxh, jnzxh
assembler/main.c +114 -0
@@ -503,6 +503,106 @@do_assemble_insn (ctx, insn, opcode); } +static unsigned int merge_ext_into_opcode_human (struct assembler_context *ctx, +unsigned int opbase, +struct instruction *insn) +{ +struct operlist *ol; +unsigned int opcode; + +unsigned long masks[256 ]; +unsigned long m, s, j =0 ; +unsigned long imm, shift, mask, mask2; +for (m =0 ; m <16 ; m++) { + mask = (1 << (m+1 )) -1 ; +for (s =0 ; s <16 ; s++) { + mask2 = (mask << s) | (mask >> (16 - s)); + mask2 = mask2 &0xFFFF ; + masks[j] = mask2; + j++; + } + } + + opcode = opbase; + ol = insn->operands; + +for (j =0 ; j <256 ; j++) +if (masks[j] == ((~ol->oper[5 ]->u.raw) &0xFFFF )) +break ; +if (j ==256 ) +asm_error (ctx,"can't build valid mask" ); + m = j /16 ; s = j %16 ; + mask = (1 << (m +1 )) -1 ; + mask = (mask << s) | (mask >> (16 - s)); +if (mask != ((~ol->oper[5 ]->u.raw) &0xFFFF )) +asm_error (ctx,"can't match mask" ); + +if (ol->oper[4 ]->u.raw !=0 ) +asm_error (ctx,"can't use shift here" ); + + shift = ol->oper[1 ]->u.raw; + mask = ol->oper[2 ]->u.raw; + +if (ol->oper[0 ]->type ==OPER_IMM ) { + imm = ((ol->oper[0 ]->u.imm->imm << shift) & mask) &0xFFFF ; + ol->oper[0 ]->u.imm->imm = imm; + imm = ((imm >> s) | (imm << (16 -s))) &0xFFFF ; +if (imm & ~0x3FF || + ol->oper[0 ]->u.imm->imm != (((imm << s) | (imm >> (16 -s))) &0xFFFF )) +asm_error (ctx,"immediate value can't be encoded" ); + ol->oper[0 ]->u.imm->imm = imm; + }else { +if (shift >15 ) +asm_error (ctx,"invalid shift" ); +if (mask != ((~ol->oper[5 ]->u.raw) &0xFFFF )) +asm_error (ctx,"unmatched masks" ); + } + + opcode |= (m <<4 ); + opcode |= s; + + ol->oper[1 ] = ol->oper[3 ]; + ol->oper[2 ] = ol->oper[6 ]; + +return opcode; +} + +static unsigned int merge_ext_into_opcode_human2 (struct assembler_context *ctx, +unsigned int opbase, +struct instruction *insn) +{ +struct operlist *ol; +unsigned long masks[256 ]; +unsigned long m, s, j =0 ; +unsigned long mask; +unsigned int opcode = opbase; +for (m =0 ; m <16 ; m++) { + mask = (1 << (m+1 )) -1 ; +for (s =0 ; s <16 ; s++) { + masks[j] = (mask << s) &0xFFFFFFFF ; + j++; + } + } + + ol = insn->operands; + +for (j =0 ; j <256 ; j++) +if (ol->oper[2 ]->u.imm->imm == masks[j]) +break ; +if (j ==256 ) +asm_error (ctx,"can't build valid mask" ); + m = j /16 ; s = j %16 ; + mask = (1 << (m +1 )) -1 ; + mask = (mask << s) &0xFFFFFFFF ; +if (mask != ol->oper[2 ]->u.imm->imm) +asm_error (ctx,"can't match mask" ); + opcode |= (m <<4 ); + opcode |= s; + + ol->oper[2 ] = ol->oper[3 ]; +return opcode; +} +static unsigned int merge_ext_into_opcode (struct assembler_context *ctx,unsigned int opbase,struct instruction *insn)
@@ -799,6 +899,10 @@ opcode =merge_ext_into_opcode (ctx,0x300 , insn);do_assemble_insn (ctx, insn, opcode);break ; +case OP_ORXH : + opcode =merge_ext_into_opcode_human (ctx,0x300 , insn); +do_assemble_insn (ctx, insn, opcode); +break ;case OP_MOV :emulate_mov_insn (ctx, insn);return ;
@@ -879,11 +983,21 @@ out =do_assemble_insn (ctx, insn, opcode); out->is_jump_insn =1 ;break ; +case OP_JZXH : + opcode =merge_ext_into_opcode_human2 (ctx,0x400 , insn); + out =do_assemble_insn (ctx, insn, opcode); + out->is_jump_insn =1 ; +break ;case OP_JNZX : opcode =merge_ext_into_opcode (ctx,0x500 , insn); out =do_assemble_insn (ctx, insn, opcode); out->is_jump_insn =1 ;break ; +case OP_JNZXH : + opcode =merge_ext_into_opcode_human2 (ctx,0x500 , insn); + out =do_assemble_insn (ctx, insn, opcode); + out->is_jump_insn =1 ; +break ;case OP_JEXT : opcode =merge_external_jmp_into_opcode (ctx,0x700 , insn); out =do_assemble_insn (ctx, insn, opcode);
assembler/main.h +7 -1
@@ -96,8 +96,14 @@ } u; }; +struct operand_shift_mask { +struct operand *op; +unsigned int mask; +unsigned int shift; +}; +struct operlist { -struct operand *oper[5 ]; +struct operand *oper[7 ]; };struct instruction {
assembler/parser.y +236 -1
285 lines not on this page · raw message
assembler/scanner.l +3 -0
@@ -105,6 +105,7 @@ rr { update_lineinfo(); return OP_RR; } nand { update_lineinfo(); return OP_NAND; } orx { update_lineinfo(); return OP_ORX; } +orxh { update_lineinfo(); return OP_ORXH; } mov { update_lineinfo(); return OP_MOV; } jmp { update_lineinfo(); return OP_JMP; }
@@ -127,7 +128,9 @@ jdp { update_lineinfo(); return OP_JDP; } jdnz { update_lineinfo(); return OP_JDNZ; } jzx { update_lineinfo(); return OP_JZX; } +jzxh { update_lineinfo(); return OP_JZXH; } jnzx { update_lineinfo(); return OP_JNZX; } +jnzxh { update_lineinfo(); return OP_JNZXH; } jext { update_lineinfo(); return OP_JEXT; } jnext { update_lineinfo(); return OP_JNEXT; }
assembler/test.asm +12 -0
@@ -72,6 +72,11 @@ orx 7,8,r0,r1,r2 /* eXtended OR */ + orxh 0x10, r1 & ~0x30, r2 /* r2 = 0x10 | (r1 & ~0x30) */ + orxh 0, r1 & ~0xFFF0, r2 /* r2 = r1 & ~0xFFF0 */ + orxh r1 & 0x7FFF, 0 & ~0x7FFF, r2 /* r2 = r1 & 0x7FFF */ + orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2 /* r2 = (r1 << 8) & 0x0100 | r2 & ~0x0100 */ + /* Copy instruction. This is a virtual instruction * translated to more lowlevel stuff like OR. */ mov r0,r2 /* copy data */
@@ -100,6 +105,13 @@ jzx 7,8,r0,r1,label /* Jump if zero after shift and mask */ jnzx 7,8,r0,r1,label /* Jump if nonzero after shift and mask */ + jzxh r12 & 0x18, label /* jump if result is zero */ + jzxh (r12 << 16) & 0x001FFFC0, label /* jump if result is zero */ + jzxh (r12 << 16 | r13) & 0x1F000, label /* jump if result is zero */ + jnzxh r12 & 0x18, label /* jump if result is non zero */ + jnzxh (r12 << 16) & 0x001FFFC0, label /* jump if result is non zero */ + jnzxh (r12 << 16 | r13) & 0x1F000, label /* jump if result is non zero */ + /* jump on external conditions */ jext ECOND_MAC_ON,label /* jump if external condition is TRUE */ jnext ECOND_MAC_ON,label /* jump if external condition is FALSE */
assembler/README +3 -0
@@ -43,7 +43,9 @@ ret | lrX,lrY | Store PC, ret from func | lrX=PC; PC=lrY rets | | ret from function | stack->PC jzx | M,S,A,B,l | Jump if zero after shift + mask | +jzxh | A,l | Human readable alias for jzx | See detailed docs jnzx | M,S,A,B,l | Jump if nonzero after shift+msk | +jnzxh | A,l | Human readable alias for jnzx | See detailed docs jext | E,A,B,l | Jump if External Condition true | if(E) PC=l jnext | E,A,B,l | Jump if External Condition false| if(!E) PC=l
@@ -66,6 +68,7 @@ rr | A,B,rD | Rotate right | rD=rrot(A, B bits) nand | A,B,rD | Clear bits (notmask+and) | rD=A&(~B) orx | M,S,A,B,rD | OR with shift and select | See detailed docs +orxh | A,B,rD | Human readable alias for orx | See detailed docs Other instructions: nap | none | Sleep until event | See detailed docs
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Quoted 1 line · On Sat, 12 Nov 2011 18:31:21 +0100 francesco.gringoli at ing.unibs.it wrote:
orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2
This is not really going to fly. If you want this highlevel stuff, you should port a C compiler to the architecture.
This is assembly. It doesn't know about reg<<imm or similar stuff.
Signature · 1 line
Greetings, Michael.
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Quoted 8 lines · Michael B?sch
Quoted 1 line · On Sat, 12 Nov 2011 18:31:21 +0100 francesco.gringoli at ing.unibs.it wrote:
orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2This is not really going to fly. If you want this highlevel stuff, you should port a C compiler to the architecture.
This is assembly. It doesn't know about reg<<imm or similar stuff.
Yes, you are right and, in fact, the patched assembler will just accept only what the cpu may execute, I does not pretend to be a C compiler. It's just another way for assembling "or with shift and select" (or jzx), and this way really enhances the readability of the assembly code. Give it a try :-).
If I'm not wrong, it's like "mov 0x1234, r1": such instruction doesn't exist but the assembler accepts it and converts to "orx 7, 8, 0x12, 0x34, r1". So why not adding more assembly options so that the code can be easily understood? Consider these lines
orx 0, 5, 0x001, SPR_BRC, SPR_BRC orx 0, 3, 0x000, SPR_BRC, SPR_BRC orx 1, 0, GP_REG1, SPR_TXE0_PHY_CTL, SPR_TXE0_PHY_CTL;
and compare them to
#define FRAME_BURST 0x0020
#define CONTENTION_PARAM_MODIFIED 0x0008
#define FRAME_ENCODING 0x0003
orxh FRAME_BURST, SPR_BRC & ~FRAME_BURST, SPR_BRC
orxh 0x0000, SPR_BRC & ~CONTENTION_PARAM_MODIFIED, SPR_BRC
orxh r1 & FRAME_ENCODING, SPR_TXE0_PHY_CTL & ~ FRAME_ENCODING, SPR_TXE0_PHY_CTL
Regards,
-Francesco
Quoted 3 lines
Signature · 2 lines
-- Greetings, Michael.
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Quoted 5 lines · On Sat, 12 Nov 2011 20:03:36 +0100 francesco.gringoli at ing.unibs.it wrote:
Quoted 3 lines · Michael B?sch
On Sat, 12 Nov 2011 18:31:21 +0100
francesco.gringoli at ing.unibs.it wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2This is not really going to fly. If you want this highlevel stuff, you should port a C compiler to the architecture.
This is assembly. It doesn't know about reg<<imm or similar stuff.Yes, you are right and, in fact, the patched assembler will just accept only what the cpu may execute, I does not pretend to be a C compiler. It's just another way for assembling "or with shift and select" (or jzx), and this way really enhances the readability of the assembly code. Give it a try :-).
If I'm not wrong, it's like "mov
0x1234, r1"
No.
It crosses the line where it does (pseudo)operations (like shift, and, or, etc..) on non-const (non-immediate) stuff.
Just do a preprocessor or something like that, that translates your pseudo-insns to real insns. Alternatively port a small C compiler.
I also don't think that this is easier to read for people familiar to the CPU. And you have to be familiar to the CPU when writing code for it.
I won't merge this. No way.
The "/* duplicate some complex_imm rules to avoid parentheses" part also is not really merge-able as-is. yacc knows about operator precedence. If you want operator precedence (to get rid of parenthesis), just use this yacc feature to implement this.
Signature · 1 line
Greetings, Michael.
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Quoted 21 lines · Michael B?sch
Quoted 5 lines · On Sat, 12 Nov 2011 20:03:36 +0100 francesco.gringoli at ing.unibs.it wrote:
Quoted 3 lines · Michael B?sch
On Sat, 12 Nov 2011 18:31:21 +0100
francesco.gringoli at ing.unibs.it wrote:Quoted 8 lines
Quoted 5 lines
Quoted 1 line
orxh (r1 << 8) & 0x0100, r2 & ~0x0100, r2This is not really going to fly. If you want this highlevel stuff, you should port a C compiler to the architecture.
This is assembly. It doesn't know about reg<<imm or similar stuff.Yes, you are right and, in fact, the patched assembler will just accept only what the cpu may execute, I does not pretend to be a C compiler. It's just another way for assembling "or with shift and select" (or jzx), and this way really enhances the readability of the assembly code. Give it a try :-).
If I'm not wrong, it's like "mov
0x1234, r1"No.
It crosses the line where it does (pseudo)operations (like shift, and, or, etc..) on non-const (non-immediate) stuff.
Quoted 5 lines
Just do a preprocessor or something like that, that translates your pseudo-insns to real insns. Alternatively port a small C compiler.
I also don't think that this is easier to read for people familiar to the CPU. And you have to be familiar to the CPU when writing code for it.
I initially started with a pre-processor but I soon realized that those three instructions were the only one whose readability could have been improved by the preprocessor itself.
Quoted 1 line
I won't merge this. No way.
Ok, anyway I urge to share with other researchers a new version of the standard ucode and for the moment I don't have more time to spend on the "preprocessor". I'm sorry but the new ucode source will require the patched assembler. As soon as I have finished some work on the N-PHY firmware I will come back to the preprocessor.
Quoted 3 lines
The "/* duplicate some
complex_immrules to avoid parentheses" part also is not really merge-able as-is. yacc knows about operator precedence. If you want operator precedence (to get rid of parenthesis), just use this yacc feature to implement this.
Yes, I did it this way because "[reg|mem] << imm" is not assembly (as you say :-) ) and the assembler strictly checks that such syntax is used only with "orxh".
Regards,
-Francesco
Quoted 3 lines
Signature · 2 lines
-- Greetings, Michael.
PATCH 1/1 b43-asm: Add 3 new virtual instructions.
Quoted 30 lines · On Sat, Nov 12, 2011 at 9:12 PM, <[email protected]> wrote:
Quoted 21 lines · Michael B?sch
Quoted 5 lines · On Sat, 12 Nov 2011 20:03:36 +0100 francesco.gringoli at ing.unibs.it wrote:
Quoted 3 lines · Michael B?sch
On Sat, 12 Nov 2011 18:31:21 +0100
francesco.gringoli at ing.unibs.it wrote:Quoted 8 lines
Quoted 5 lines
Quoted 1 line
? ?orxh ? ?(r1 << 8) &
0x0100, r2 & ~0x0100, r2This is not really going to fly. If you want this highlevel stuff, you should port a C compiler to the architecture.
This is assembly. It doesn't know about reg<<imm or similar stuff.Yes, you are right and, in fact, the patched assembler will just accept only what the cpu may execute, I does not pretend to be a C compiler. It's just another way for assembling "or with shift and select" (or jzx), and this way really enhances the readability of the assembly code. Give it a try :-).
If I'm not wrong, it's like "mov
0x1234, r1"No.
It crosses the line where it does (pseudo)operations (like shift, and, or, etc..) on non-const (non-immediate) stuff.Quoted 5 lines
Just do a preprocessor or something like that, that translates your pseudo-insns to real insns. Alternatively port a small C compiler.
I also don't think that this is easier to read for people familiar to the CPU. And you have to be familiar to the CPU when writing code for it.
I initially started with a pre-processor but I soon realized that those three instructions were the only one whose readability could have been improved by the preprocessor itself.
Quoted 7 lines
Quoted 1 line
I won't merge this. No way.
Ok, anyway I urge to share with other researchers ?a new version of the standard ucode and for the moment I don't have more time to spend on the "preprocessor". I'm sorry but the new ucode source will require the patched assembler. As soon as I have finished some work on the N-PHY firmware I will come back to the preprocessor.
Quoted 3 lines
The "/* duplicate some
complex_immrules to avoid parentheses" part also is not really merge-able as-is. yacc knows about operator precedence. If you want operator precedence (to get rid of parenthesis), just use this yacc feature to implement this.Yes, I did it this way because "[reg|mem] << imm" is not assembly (as you say :-) ) and the assembler strictly checks that such syntax is used only with "orxh".
Well, in x86, we have "mov eax, es:[bx+di]". A lot more readable than, say, "mov eax, es, bx, di".
Quoted 14 lines
Regards,
-FrancescoQuoted 3 lines
--
Greetings, Michael._______________________________________________
b43-dev mailing list
b43-dev at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/b43-dev
Signature · 1 line
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)