ppc64: fixes for ppc64 objdump
The current output for the Go objdump on ppc64 is not correct in many cases, generating opcodes that are not acceptable by the Go assembler, and generating operands in the wrong order. This adds some changes to generate an objdump for ppc64 code so that the instructions generated are acceptable by the Go assembler, and where some of the non-obvious operands have more meaningful names. This includes the following changes: - Correct some errors in ppc64map to make it work. - Make a minor update to ppc64.csv to add the Go opcodes that have been added to the Go assembler that were not in the table. - Fix ppc64map to generate correct Go opcodes for ppc64 opcodes that end with '.' indicating condition codes are set. The previous ppc64map was adding '_' at the end for this case, but then had to be translated in plan9.go to 'CC' and many were not being translated. This generates the correct suffix in the first step when generating tables.go. - Handle compare instructions correctly, since the names don't quite match and the CR was not always handled correctly. - Handle index loads and stores correctly, including VMX and VSX. - Add mappings for all the names where the Go opcode does not match the ppc64 opcode. - Handle all CR values, not just CR0 for those instructions that use them. - Provide more information on BC instructions and generate the correct branch mnemonic (BEQ, BNE, etc.) where possible. - Make the output more consistent in spacing. - Add some more testcases to testdata/decode.txt. - If the instruction word is all 0s, the Go assembler will output WORD $0, otherwise unrecognized instructions will be identified with '?'. For GNU, all 0s will decode to .long 0x0 like the binutils objdump. This can happen following a call to a panic or throw as a trap, or at the end of a function for alignment purposes. Note: the decoder does not handle extended opcodes correctly yet. I will add that support in the next release and add the corresponding testcases. We are working on an updated ppc64.csv, but I believe what is there now covers the opcodes that are supported by the Go assembler. Change-Id: If7fe1a2205512b476f4fb6b29a21f5459430e50c Reviewed-on: https://go-review.googlesource.com/c/148574 Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Родитель
b19384d3c1
Коммит
5a4828bb70
|
@ -1198,3 +1198,23 @@
|
|||
"Move From Link Register R-form","se_mflr RX","0@0|8@6|RX@12@15|",""
|
||||
"Move To Link Register R-form","se_mtlr RX","0@0|9@6|RX@12@15|",""
|
||||
"Instruction Synchronize C-form","se_isync","01@0@15|",""
|
||||
"Add Extended using alternate carry bit Z23-form","addex RT,RA,RB,CY","31@0|RT@6|RA@11|RB@16|CY@21|170@23|/@31|",""
|
||||
"Deliver A Random Number X-form","darn RT,L","31@0|RT@6|///@11|L@14|///@16|755@21|/@31|",""
|
||||
"Multiply-Add High Doubleword VA-form","maddhd RT,RA,RB,RC","4@0|RT@6|RA@11|RB@16|RC@21|48@26|",""
|
||||
"Multiply-Add High Doubleword Unsigned VA-form","maddhdu RT,RA,RB,RC","4@0|RT@6|RA@11|RB@16|RC@21|49@26|",""
|
||||
"Multiply-Add Low Doubleword VA-form","maddld RT,RA,RB,RC","4@0|RT@6|RA@11|RB@16|RC@21|51@26|",""
|
||||
"Compare Ranged Byte X-form","cmprb BF,L,RA,RB","31@0|BF@6|/@9|L@10|RA@11|RB@16|192@21|/@31|",""
|
||||
"Compare Equal Byte X-form","cmpeqb BF,RA,RB","31@0|BF@6|//@9|RA@11|RB@16|224@21|/@31|",""
|
||||
"Bit Permute Doubleword X-form","bpermd RA,RS,RB]","31@0|RS@6|RA@11|RB@16|252@21|/@31|",""
|
||||
"Extend-Sign Word and Shift Left Immediate XS-form","extswsli RA,RS,SH ( Rc=0 )|extswsli. RA,RS,SH ( Rc=1 )","31@0|RS@6|RA@11|sh@16|445@21|sh@30|Rc@31|",""
|
||||
"Move From VSR Doubleword X-form","mfvsrd RA,XS","31@0|S@6|RA@11|///@16|51@21|SX@31|",""
|
||||
"Move From VSR Lower Doubleword X-form","mfvsrld RA,XS","31@0|S@6|RA@11|///@16|307@21|SX@31|",""
|
||||
"Move From VSR Word and Zero X-form","mfvsrwz RA,XS","31@0|S@6|RA@11|///@16|115@21|SX@31|",""
|
||||
"Move To VSR Doubleword X-form","mtvsrd XT,RA","31@0|T@6|RA@11|///@16|179@21|TX@31|",""
|
||||
"Move To VSR Word Algebraic X-form","mtvsrwa XT,RA","31@0|T@6|RA@11|///@16|211@21|TX@31|",""
|
||||
"Move To VSR Word and Zero X-form","mtvsrwz XT,RA","31@0|T@6|RA@11|///@16|243@21|TX@31|",""
|
||||
"Move To VSR Double Doubleword X-form","mtvsrdd XT,RA,RB","31@0|T@6|RA@11|RB@16|435@21|TX@31|",""
|
||||
"Move To VSR Word & Splat X-form","mtvsrws XT,RA","31@0|T@6|RA@11|///@16|403@21|TX@31|",""
|
||||
"Move to CR from XER Extended X-form","mcrxrx BF","31@0|BF@6|//@9|///@11|///@16|576@21|/@31|",""
|
||||
"Copy X-form","copy RA,RB","31@0|///@6|1@10|RA@11|RB@16|774@21|/@31|",""
|
||||
"Paste X-form","paste. RA,RB","31@0|///@6|1@10|RA@11|RB@16|902@21|1@31|",""
|
||||
|
|
Не удается отобразить этот файл, потому что он имеет неправильное количество полей в строке 3.
|
|
@ -172,7 +172,7 @@ func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
if inst.Op == 0 {
|
||||
if inst.Op == 0 && inst.Enc != 0 {
|
||||
return inst, errUnknown
|
||||
}
|
||||
return inst, nil
|
||||
|
|
|
@ -50,8 +50,8 @@ func TestDecode(t *testing.T) {
|
|||
switch syntax {
|
||||
case "gnu":
|
||||
out = GNUSyntax(inst)
|
||||
//case "plan9":
|
||||
// out = GoSyntax(inst, 0, nil, nil)
|
||||
case "plan9":
|
||||
out = GoSyntax(inst, 0, nil)
|
||||
default:
|
||||
t.Errorf("unknown syntax %q", syntax)
|
||||
continue
|
||||
|
|
|
@ -14,8 +14,12 @@ import (
|
|||
// This form typically matches the syntax defined in the Power ISA Reference Manual.
|
||||
func GNUSyntax(inst Inst) string {
|
||||
var buf bytes.Buffer
|
||||
if inst.Op == 0 {
|
||||
return "error: unkown instruction"
|
||||
// When there are all 0s, identify them as the disassembler
|
||||
// in binutils would.
|
||||
if inst.Enc == 0 {
|
||||
return ".long 0x0"
|
||||
} else if inst.Op == 0 {
|
||||
return "error: unknown instruction"
|
||||
}
|
||||
buf.WriteString(inst.Op.String())
|
||||
sep := " "
|
||||
|
|
|
@ -49,11 +49,11 @@ func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool
|
|||
switch inst.Op {
|
||||
case BC, BCA, BL, BLA, BCL, BCLA, TDI, TWI, TW, TD:
|
||||
return true // TODO(minux): we lack the support for extended opcodes here
|
||||
case RLWNM, RLWNM_, RLDICL, RLDICL_, RLWINM, RLWINM_, RLDCL, RLDCL_:
|
||||
case RLWNM, RLWNMCC, RLDICL, RLDICLCC, RLWINM, RLWINMCC, RLDCL, RLDCLCC:
|
||||
return true // TODO(minux): we lack the support for extended opcodes here
|
||||
case DCBTST, DCBT:
|
||||
return true // objdump uses the embedded argument order, we use the server argument order
|
||||
case MTFSF, MTFSF_: // objdump doesn't show the last two arguments
|
||||
case MTFSF, MTFSFCC: // objdump doesn't show the last two arguments
|
||||
return true
|
||||
case VSPLTB, VSPLTH, VSPLTW: // objdump generates unreasonable result "vspltw v6,v19,4" for 10c49a8c, the last 4 should be 0.
|
||||
return true
|
||||
|
|
|
@ -19,7 +19,9 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
|
|||
if symname == nil {
|
||||
symname = func(uint64) (string, uint64) { return "", 0 }
|
||||
}
|
||||
if inst.Op == 0 {
|
||||
if inst.Op == 0 && inst.Enc == 0 {
|
||||
return "WORD $0"
|
||||
} else if inst.Op == 0 {
|
||||
return "?"
|
||||
}
|
||||
var args []string
|
||||
|
@ -28,13 +30,27 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
|
|||
break
|
||||
}
|
||||
if s := plan9Arg(&inst, i, pc, a, symname); s != "" {
|
||||
args = append(args, s)
|
||||
// In the case for some BC instructions, a CondReg arg has
|
||||
// both the CR and the branch condition encoded in its value.
|
||||
// plan9Arg will return a string with the string representation
|
||||
// of these values separated by a blank that will be treated
|
||||
// as 2 args from this point on.
|
||||
if strings.IndexByte(s, ' ') > 0 {
|
||||
t := strings.Split(s, " ")
|
||||
args = append(args, t[0])
|
||||
args = append(args, t[1])
|
||||
} else {
|
||||
args = append(args, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
var op string
|
||||
op = plan9OpMap[inst.Op]
|
||||
if op == "" {
|
||||
op = strings.ToUpper(inst.Op.String())
|
||||
if op[len(op)-1] == '.' {
|
||||
op = op[:len(op)-1] + "CC"
|
||||
}
|
||||
}
|
||||
// laid out the instruction
|
||||
switch inst.Op {
|
||||
|
@ -45,15 +61,60 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
|
|||
return fmt.Sprintf("%s %s", op, args[0])
|
||||
}
|
||||
args = append(args, args[0])
|
||||
return op + " " + strings.Join(args[1:], ", ")
|
||||
return op + " " + strings.Join(args[1:], ",")
|
||||
case SYNC:
|
||||
if args[0] == "$1" {
|
||||
return "LWSYNC"
|
||||
}
|
||||
return "HWSYNC"
|
||||
|
||||
case ISEL:
|
||||
return "ISEL " + args[3] + "," + args[1] + "," + args[2] + "," + args[0]
|
||||
|
||||
// store instructions always have the memory operand at the end, no need to reorder
|
||||
case STB, STBU, STBX, STBUX,
|
||||
STH, STHU, STHX, STHUX,
|
||||
STW, STWU, STWX, STWUX,
|
||||
STD, STDU, STDX, STDUX,
|
||||
STQ,
|
||||
STHBRX, STWBRX:
|
||||
return op + " " + strings.Join(args, ", ")
|
||||
// indexed stores handled separately
|
||||
case STB, STBU,
|
||||
STH, STHU,
|
||||
STW, STWU,
|
||||
STD, STDU,
|
||||
STQ:
|
||||
return op + " " + strings.Join(args, ",")
|
||||
|
||||
case CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI:
|
||||
if len(args) == 2 {
|
||||
return op + " " + args[0] + "," + args[1]
|
||||
} else if len(args) == 3 {
|
||||
return op + " " + args[0] + "," + args[1] + "," + args[2]
|
||||
}
|
||||
return op + " " + args[0] + " ??"
|
||||
|
||||
case LIS:
|
||||
return "ADDIS $0," + args[1] + "," + args[0]
|
||||
// store instructions with index registers
|
||||
case STBX, STBUX, STHX, STHUX, STWX, STWUX, STDX, STDUX,
|
||||
STHBRX, STWBRX, STDBRX, STSWX, STFSX, STFSUX, STFDX, STFDUX, STFIWX, STFDPX:
|
||||
return "MOV" + op[2:len(op)-1] + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
|
||||
|
||||
case STDCXCC, STWCXCC, STHCXCC, STBCXCC:
|
||||
return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
|
||||
|
||||
case STXVD2X, STXVW4X:
|
||||
return op + " " + args[0] + ",(" + args[2] + ")(" + args[1] + ")"
|
||||
|
||||
// load instructions with index registers
|
||||
case LBZX, LBZUX, LHZX, LHZUX, LWZX, LWZUX, LDX, LDUX,
|
||||
LHBRX, LWBRX, LDBRX, LSWX, LFSX, LFSUX, LFDX, LFDUX, LFIWAX, LFIWZX:
|
||||
return "MOV" + op[1:len(op)-1] + " (" + args[2] + ")(" + args[1] + ")," + args[0]
|
||||
|
||||
case LDARX, LWARX, LHARX, LBARX:
|
||||
return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
|
||||
|
||||
case LXVD2X, LXVW4X:
|
||||
return op + " (" + args[2] + ")(" + args[1] + ")," + args[0]
|
||||
|
||||
case DCBT, DCBTST, DCBZ, DCBST:
|
||||
return op + " (" + args[1] + ")"
|
||||
|
||||
// branch instructions needs additional handling
|
||||
case BCLR:
|
||||
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
|
||||
|
@ -62,11 +123,17 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
|
|||
return op + " " + strings.Join(args, ", ")
|
||||
case BC:
|
||||
if int(inst.Args[0].(Imm))&0x1c == 12 { // jump on cond bit set
|
||||
if len(args) == 4 {
|
||||
return fmt.Sprintf("B%s %s,%s", args[1], args[2], args[3])
|
||||
}
|
||||
return fmt.Sprintf("B%s %s", args[1], args[2])
|
||||
} else if int(inst.Args[0].(Imm))&0x1c == 4 && revCondMap[args[1]] != "" { // jump on cond bit not set
|
||||
if len(args) == 4 {
|
||||
return fmt.Sprintf("B%s %s,%s", revCondMap[args[1]], args[2], args[3])
|
||||
}
|
||||
return fmt.Sprintf("B%s %s", revCondMap[args[1]], args[2])
|
||||
}
|
||||
return op + " " + strings.Join(args, ", ")
|
||||
return op + " " + strings.Join(args, ",")
|
||||
case BCCTR:
|
||||
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
|
||||
return "BR (CTR)"
|
||||
|
@ -76,9 +143,9 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin
|
|||
if int(inst.Args[0].(Imm))&20 == 20 { // unconditional
|
||||
return "BL (CTR)"
|
||||
}
|
||||
return op + " " + strings.Join(args, ", ")
|
||||
return op + " " + strings.Join(args, ",")
|
||||
case BCA, BCL, BCLA, BCLRL, BCTAR, BCTARL:
|
||||
return op + " " + strings.Join(args, ", ")
|
||||
return op + " " + strings.Join(args, ",")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +169,10 @@ func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64)
|
|||
}
|
||||
return strings.ToUpper(arg.String())
|
||||
case CondReg:
|
||||
// This op is left as its numerical value, not mapped onto CR + condition
|
||||
if inst.Op == ISEL {
|
||||
return fmt.Sprintf("$%d", (arg - Cond0LT))
|
||||
}
|
||||
if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
|
||||
return "" // don't show cr0 for cmp instructions
|
||||
} else if arg >= CR0 {
|
||||
|
@ -111,7 +182,7 @@ func plan9Arg(inst *Inst, argIndex int, pc uint64, arg Arg, symname func(uint64)
|
|||
if arg <= Cond0SO {
|
||||
return bit
|
||||
}
|
||||
return fmt.Sprintf("4*CR%d+%s", int(arg-Cond0LT)/4, bit)
|
||||
return fmt.Sprintf("%s CR%d", bit, int(arg-Cond0LT)/4)
|
||||
case Imm:
|
||||
return fmt.Sprintf("$%d", arg)
|
||||
case SpReg:
|
||||
|
@ -148,25 +219,27 @@ var revCondMap = map[string]string{
|
|||
|
||||
// plan9OpMap maps an Op to its Plan 9 mnemonics, if different than its GNU mnemonics.
|
||||
var plan9OpMap = map[Op]string{
|
||||
LWARX: "LWAR", STWCX_: "STWCCC",
|
||||
LDARX: "LDAR", STDCX_: "STDCCC",
|
||||
LHARX: "LHAR", STHCX_: "STHCCC",
|
||||
LBARX: "LBAR", STBCX_: "STBCCC",
|
||||
ADDI: "ADD",
|
||||
ADD_: "ADDCC",
|
||||
LBZ: "MOVBZ", STB: "MOVB",
|
||||
LBZU: "MOVBZU", STBU: "MOVBU", // TODO(minux): indexed forms are not handled
|
||||
LWARX: "LWAR",
|
||||
LDARX: "LDAR",
|
||||
LHARX: "LHAR",
|
||||
LBARX: "LBAR",
|
||||
ADDI: "ADD",
|
||||
SRADI: "SRAD",
|
||||
SUBF: "SUB",
|
||||
LI: "MOVD",
|
||||
LBZ: "MOVBZ", STB: "MOVB",
|
||||
LBZU: "MOVBZU", STBU: "MOVBU",
|
||||
LHZ: "MOVHZ", LHA: "MOVH", STH: "MOVH",
|
||||
LHZU: "MOVHZU", STHU: "MOVHU",
|
||||
LI: "MOVD",
|
||||
LIS: "ADDIS",
|
||||
LWZ: "MOVWZ", LWA: "MOVW", STW: "MOVW",
|
||||
LWZU: "MOVWZU", STWU: "MOVWU",
|
||||
LD: "MOVD", STD: "MOVD",
|
||||
LDU: "MOVDU", STDU: "MOVDU",
|
||||
CMPD: "CMP", CMPDI: "CMP",
|
||||
CMPW: "CMPW", CMPWI: "CMPW",
|
||||
CMPLD: "CMPU", CMPLDI: "CMPU",
|
||||
CMPLW: "CMPWU", CMPLWI: "CMPWU",
|
||||
MTSPR: "MOVD", MFSPR: "MOVD", // the width is ambiguous for SPRs
|
||||
B: "BR",
|
||||
BL: "CALL",
|
||||
CMPLD: "CMPU", CMPLW: "CMPWU",
|
||||
CMPD: "CMP", CMPW: "CMPW",
|
||||
B: "BR",
|
||||
BL: "CALL",
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,25 +1,56 @@
|
|||
6d746162| gnu xoris r20,r11,24930
|
||||
6d746162| plan9 XORIS R11,$24930,R20
|
||||
4c040000| gnu mcrf cr0,cr1
|
||||
88000017| gnu lbz r0,23(0)
|
||||
4abaa88a| gnu ba 0xfebaa888
|
||||
7d8fc2a6| gnu mfspr r12,783
|
||||
00000000| gnu error: unknown instruction
|
||||
88a70002| gnu lbz r5,2(r7)
|
||||
88a70002| plan9 MOVBZ 2(R7),R5
|
||||
00000000| plan9 WORD $0
|
||||
00010000| plan9 error: unknown instruction
|
||||
00000000| gnu .long 0x0
|
||||
00002000| gnu error: unknown instruction
|
||||
a1841e80| gnu lhz r12,7808(r4)
|
||||
a1841e80| plan9 MOVHZ 7808(R4),R12
|
||||
42093d10| gnu bc 16,4*cr2+gt,.+0x3d10
|
||||
e38d5b90| gnu lq r28,23440(r13)
|
||||
84127a20| gnu lwzu r0,31264(r18)
|
||||
c61bb730| gnu lfsu f16,-18640(r27)
|
||||
0825f440| gnu tdi 1,r5,-3008
|
||||
a9a912c1| gnu lha r13,4801(r9)
|
||||
84127a20| plan9 MOVWZU 31264(R18),R0
|
||||
a8630000| gnu lha r3,0(r3)
|
||||
a8630000| plan9 MOVH 0(R3),R3
|
||||
ebb24fd1| gnu ldu r29,20432(r18)
|
||||
ebb24fd1| plan9 MOVDU 20432(R18),R29
|
||||
b1ce0612| gnu sth r14,1554(r14)
|
||||
f3c04322| gnu xvcvdpuxws vs30,vs40
|
||||
b1ce0612| plan9 MOVH R14,1554(R14)
|
||||
945c62a2| gnu stwu r2,25250(r28)
|
||||
9c8156e3| gnu stbu r4,22243(r1)
|
||||
f91b9c7a| gnu stq r8,-25480(r27)
|
||||
2c1c81b4| gnu cmpwi r28,-32332
|
||||
f87b904d| gnu stdu r3,-28596(r27)
|
||||
eab3c832| gnu lwa r21,-14288(r19)
|
||||
2c030001| gnu cmpwi r3,1
|
||||
2c030001| plan9 CMPW R3,$1
|
||||
e8610032| gnu lwa r3,48(r1)
|
||||
e8610032| plan9 MOVW 48(R1),R3
|
||||
4320336b| gnu bcla 25,lt,0x3368
|
||||
7e40092e| gnu stwx r18,0,r1
|
||||
7e40092e| plan9 MOVW R18,(R1)(0)
|
||||
7c103c2c| gnu lwbrx r0,r16,r7
|
||||
7c103c2c| plan9 MOVWBR (R7)(R16),R0
|
||||
7c441d28| gnu stdbrx r2,r4,r3
|
||||
7c441d28| plan9 MOVDBR R2,(R3)(R4)
|
||||
3d220001| gnu addis r9,r2,1
|
||||
3d220001| plan9 ADDIS R2,$1,R9
|
||||
7ce628ae| gnu lbzx r7,r6,r5
|
||||
7ce628ae| plan9 MOVBZ (R5)(R6),R7
|
||||
7c0e1e99| gnu lxvd2x vs32,r14,r3
|
||||
7c0e1e99| plan9 LXVD2X (R3)(R14),VS32
|
||||
7c00422c| gnu dcbt r0,r8,0
|
||||
7c00422c| plan9 DCBT (R8)
|
||||
7fab3040| gnu cmpld cr7,r11,r6
|
||||
7fab3040| plan9 CMPU CR7,R11,R6
|
||||
2c030001| gnu cmpwi r3,1
|
||||
2c030001| plan9 CMPW R3,$1
|
||||
7c2b4840| gnu cmpld r11,r9
|
||||
7c2b4840| plan9 CMPU R11,R9
|
||||
7c6521ad| gnu stdcx. r3,r5,r4
|
||||
7c6521ad| plan9 STDCXCC R3,(R4)(R5)
|
||||
fbe1ffd1| gnu stdu r31,-48(r1)
|
||||
fbe1ffd1| plan9 MOVDU R31,-48(R1)
|
||||
7c941f19| gnu stxvw4x vs36,r20,r3
|
||||
7c941f19| plan9 STXVW4X VS36,(R3)(R20)
|
||||
7c6520a8| gnu ldarx r3,r5,r4
|
||||
7c6520a8| plan9 LDAR (R4)(R5),R3
|
||||
|
|
|
@ -67,7 +67,6 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
print(p)
|
||||
}
|
||||
|
||||
|
@ -214,6 +213,7 @@ func add(p *Prog, text, mnemonics, encoding, tags string) {
|
|||
// And note the MSB is bit 0, not bit 31.
|
||||
// Example: "31@0|RS@6|RA@11|///@16|26@21|Rc@31|"
|
||||
var args Args
|
||||
var err error
|
||||
fields := strings.Split(encoding, "|")
|
||||
for i, f := range fields {
|
||||
name, off := "", -1
|
||||
|
@ -229,7 +229,16 @@ func add(p *Prog, text, mnemonics, encoding, tags string) {
|
|||
fmt.Fprintf(os.Stderr, "%s: wrong %d-th encoding field: %q\n", text, i, f)
|
||||
continue
|
||||
}
|
||||
off, _ = strconv.Atoi(f[j+1:])
|
||||
k := strings.Index(f[j+1:], " ")
|
||||
if k >= 0 {
|
||||
if strings.HasSuffix(f[j+1:], " 31") {
|
||||
f = f[:len(f)-3]
|
||||
}
|
||||
}
|
||||
off, err = strconv.Atoi(f[j+1:])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "err for: %s has: %s for %s\n", f[:j], err, f[j+1:])
|
||||
}
|
||||
name = f[:j]
|
||||
}
|
||||
if len(args) > 0 {
|
||||
|
@ -355,7 +364,7 @@ func add(p *Prog, text, mnemonics, encoding, tags string) {
|
|||
} else {
|
||||
opr = "BD"
|
||||
}
|
||||
case "UI", "BO", "BH", "TH", "LEV", "NB", "L", "TO", "FXM", "U", "W", "FLM", "UIM", "SHB", "SHW", "ST", "SIX", "PS", "DCM", "DGM", "RMC", "R", "SP", "S", "DM", "CT", "EH", "E", "MO", "WC", "A", "IH", "OC", "DUI", "DUIS":
|
||||
case "UI", "BO", "BH", "TH", "LEV", "NB", "L", "TO", "FXM", "FC", "U", "W", "FLM", "UIM", "IMM8", "RIC", "PRS", "SHB", "SHW", "ST", "SIX", "PS", "DCM", "DCMX", "DGM", "RMC", "R", "SP", "S", "DM", "CT", "EH", "E", "MO", "WC", "A", "IH", "OC", "DUI", "DUIS", "CY":
|
||||
typ = asm.TypeImmUnsigned
|
||||
if i := args.Find(opr); i < 0 {
|
||||
opr = "D"
|
||||
|
@ -397,7 +406,7 @@ func add(p *Prog, text, mnemonics, encoding, tags string) {
|
|||
opr = "SI"
|
||||
break
|
||||
}
|
||||
case "RA", "RB", "RS", "RSp", "RT", "RTp":
|
||||
case "RA", "RB", "RC", "RS", "RSp", "RT", "RTp":
|
||||
typ = asm.TypeReg
|
||||
case "BT", "BA", "BB", "BC", "BI":
|
||||
typ = asm.TypeCondRegBit
|
||||
|
@ -414,8 +423,6 @@ func add(p *Prog, text, mnemonics, encoding, tags string) {
|
|||
case "SPR", "DCRN", "BHRBE", "TBR", "SR", "TMR", "PMRN": // Note: if you add to this list and the register field needs special handling, add it to switch statement below
|
||||
typ = asm.TypeSpReg
|
||||
switch opr {
|
||||
case "BHRBE":
|
||||
opr = "bhrbe" // no special handling
|
||||
case "DCRN":
|
||||
opr = "DCR"
|
||||
}
|
||||
|
@ -501,7 +508,7 @@ func printText(p *Prog) {
|
|||
|
||||
// opName translate an opcode to a valid Go identifier all-cap op name.
|
||||
func opName(op string) string {
|
||||
return strings.ToUpper(strings.Replace(op, ".", "_", 1))
|
||||
return strings.ToUpper(strings.Replace(op, ".", "CC", 1))
|
||||
}
|
||||
|
||||
// argFieldName constructs a name for the argField
|
||||
|
|
Загрузка…
Ссылка в новой задаче