2010-07-08 Tejas Belagod <tejas.belagod@arm.com>

gas/testsuite
	* gas/arm/barrier.s: New file.
	* gas/arm/barrier.d: New file.
	* gas/arm/barrier-thumb.s: New file.
	* gas/arm/barrier-thumb.d: New file.
	* gas/arm/barrier-bad.s: New file.
	* gas/arm/barrier-bad.d: New file.
	* gas/arm/barrier-bad.l: New file.
	* gas/arm/barrier-bad-thumb.s: New file.
	* gas/arm/barrier-bad-thumb.d: New file.
	* gas/arm/barrier-bad-thumb.l: New file.

	gas/config
	* tc-arm.c (OP_oBARRIER): Remove.
	(OP_oBARRIER_I15): Add.
	(po_barrier_or_imm): Add macro.
	(parse_operands): Improve OP_oBARRIER_I15 operand parsing.
	(do_barrier): Check correct immediate range.
	(do_t_barrier): Likewise.
	(barrier_opt_names): Add entries for more symbolic operands.
	(insns): Replace OP_oBARRIER with OP_oBARRIER_I15 for barriers.

	opcodes/
	* arm-dis.c (print_insn_arm): Add cases for printing more
	symbolic operands.
	(print_insn_thumb32): Likewise.
This commit is contained in:
Richard Earnshaw 2010-07-08 22:40:28 +00:00
parent 7e6e39e562
commit 52e7f43db0
15 changed files with 469 additions and 28 deletions

View File

@ -1,3 +1,14 @@
2010-07-08 Tejas Belagod <tejas.belagod@arm.com>
* tc-arm.c (OP_oBARRIER): Remove.
(OP_oBARRIER_I15): Add.
(po_barrier_or_imm): Add macro.
(parse_operands): Improve OP_oBARRIER_I15 operand parsing.
(do_barrier): Check correct immediate range.
(do_t_barrier): Likewise.
(barrier_opt_names): Add entries for more symbolic operands.
(insns): Replace OP_oBARRIER with OP_oBARRIER_I15 for barriers.
2010-07-08 Daniel Gutson <dgutson@codesourcery.com>
* config/tc-arm.c (tc_gen_reloc): Add BFD_RELOC_ARM_T32_OFFSET_IMM

View File

@ -5898,7 +5898,7 @@ enum operand_parse_code
OP_oSHar, /* ASR immediate */
OP_oSHllar, /* LSL or ASR immediate */
OP_oROR, /* ROR 0/8/16/24 */
OP_oBARRIER, /* Option argument for a barrier instruction. */
OP_oBARRIER_I15, /* Option argument for a barrier instruction. */
/* Some pre-defined mixed (ARM/THUMB) operands. */
OP_RR_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RR, OP_RRnpcsp),
@ -6008,6 +6008,30 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
} \
while (0)
#define po_barrier_or_imm(str) \
do \
{ \
val = parse_barrier (&str); \
if (val == FAIL) \
{ \
if (ISALPHA (*str)) \
goto failure; \
else \
goto immediate; \
} \
else \
{ \
if ((inst.instruction & 0xf0) == 0x60 \
&& val != 0xf) \
{ \
/* ISB can only take SY as an option. */ \
inst.error = _("invalid barrier type"); \
goto failure; \
} \
} \
} \
while (0)
skip_whitespace (str);
for (i = 0; upat[i] != OP_stop; i++)
@ -6313,7 +6337,12 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
case OP_oROR: val = parse_ror (&str); break;
case OP_PSR: val = parse_psr (&str); break;
case OP_COND: val = parse_cond (&str); break;
case OP_oBARRIER:val = parse_barrier (&str); break;
case OP_oBARRIER_I15:
po_barrier_or_imm (str); break;
immediate:
if (parse_immediate (&str, &val, 0, 15, TRUE) == FAIL)
goto failure;
break;
case OP_RVC_PSR:
po_reg_or_goto (REG_TYPE_VFC, try_psr);
@ -6481,7 +6510,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
case OP_PSR:
case OP_RVC_PSR:
case OP_COND:
case OP_oBARRIER:
case OP_oBARRIER_I15:
case OP_REGLST:
case OP_VRSLST:
case OP_VRDLST:
@ -6546,6 +6575,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
#undef po_reg_or_goto
#undef po_imm_or_fail
#undef po_scalar_or_fail
#undef po_barrier_or_imm
/* Shorthand macro for instruction encoding functions issuing errors. */
#define constraint(expr, err) \
@ -7124,7 +7154,8 @@ do_barrier (void)
if (inst.operands[0].present)
{
constraint ((inst.instruction & 0xf0) != 0x40
&& inst.operands[0].imm != 0xf,
&& inst.operands[0].imm > 0xf
&& inst.operands[0].imm < 0x0,
_("bad barrier type"));
inst.instruction |= inst.operands[0].imm;
}
@ -9431,7 +9462,8 @@ do_t_barrier (void)
if (inst.operands[0].present)
{
constraint ((inst.instruction & 0xf0) != 0x40
&& inst.operands[0].imm != 0xf,
&& inst.operands[0].imm > 0xf
&& inst.operands[0].imm < 0x0,
_("bad barrier type"));
inst.instruction |= inst.operands[0].imm;
}
@ -16283,10 +16315,18 @@ static const struct asm_cond conds[] =
static struct asm_barrier_opt barrier_opt_names[] =
{
{ "sy", 0xf },
{ "un", 0x7 },
{ "st", 0xe },
{ "unst", 0x6 }
{ "sy", 0xf }, { "SY", 0xf },
{ "un", 0x7 }, { "UN", 0x7 },
{ "st", 0xe }, { "ST", 0xe },
{ "unst", 0x6 }, { "UNST", 0x6 },
{ "ish", 0xb }, { "ISH", 0xb },
{ "sh", 0xb }, { "SH", 0xb },
{ "ishst", 0xa }, { "ISHST", 0xa },
{ "shst", 0xa }, { "SHST", 0xa },
{ "nsh", 0x7 }, { "NSH", 0x7 },
{ "nshst", 0x6 }, { "NSHST", 0x6 },
{ "osh", 0x3 }, { "OSH", 0x3 },
{ "oshst", 0x2 }, { "OSHST", 0x2 }
};
/* Table of ARM-format instructions. */
@ -17002,9 +17042,9 @@ static const struct asm_opcode insns[] =
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_barrier
TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER), barrier, t_barrier),
TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER), barrier, t_barrier),
TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER), barrier, t_barrier),
TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER_I15), barrier, t_barrier),
TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER_I15), barrier, t_barrier),
TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER_I15), barrier, t_barrier),
/* ARM V7 instructions. */
#undef ARM_VARIANT

View File

@ -1,3 +1,16 @@
2010-07-08 Tejas Belagod <tejas.belagod@arm.com>
* gas/arm/barrier.s: New file.
* gas/arm/barrier.d: New file.
* gas/arm/barrier-thumb.s: New file.
* gas/arm/barrier-thumb.d: New file.
* gas/arm/barrier-bad.s: New file.
* gas/arm/barrier-bad.d: New file.
* gas/arm/barrier-bad.l: New file.
* gas/arm/barrier-bad-thumb.s: New file.
* gas/arm/barrier-bad-thumb.d: New file.
* gas/arm/barrier-bad-thumb.l: New file.
2010-07-08 Daniel Gutson <dgutson@codesourcery.com>
* gas/arm/reloc-bad.d: New.

View File

@ -0,0 +1,3 @@
#name: All options expect SY are reserved for ISB
#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
#error-output: barrier-bad-thumb.l

View File

@ -0,0 +1,8 @@
[^:]*: Assembler messages:
[^:]*:4: Error: invalid barrier type -- `isb st'
[^:]*:5: Error: invalid barrier type -- `isb ish'
[^:]*:6: Error: invalid barrier type -- `isb ishst'
[^:]*:7: Error: invalid barrier type -- `isb nsh'
[^:]*:8: Error: invalid barrier type -- `isb nshst'
[^:]*:9: Error: invalid barrier type -- `isb osh'
[^:]*:10: Error: invalid barrier type -- `isb oshst'

View File

@ -0,0 +1,11 @@
.syntax unified
.thumb
.arch armv7a
isb st
isb ish
isb ishst
isb nsh
isb nshst
isb osh
isb oshst

View File

@ -0,0 +1,3 @@
#name: All options expect SY are reserved for ISB
#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
#error-output: barrier-bad.l

View File

@ -0,0 +1,8 @@
[^:]*: Assembler messages:
[^:]*:3: Error: invalid barrier type -- `isb st'
[^:]*:4: Error: invalid barrier type -- `isb ish'
[^:]*:5: Error: invalid barrier type -- `isb ishst'
[^:]*:6: Error: invalid barrier type -- `isb nsh'
[^:]*:7: Error: invalid barrier type -- `isb nshst'
[^:]*:8: Error: invalid barrier type -- `isb osh'
[^:]*:9: Error: invalid barrier type -- `isb oshst'

View File

@ -0,0 +1,10 @@
.syntax unified
.arch armv7a
isb st
isb ish
isb ishst
isb nsh
isb nshst
isb osh
isb oshst

View File

@ -0,0 +1,73 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: Barrier Instruction Operands
#as: -mcpu=cortex-a8
# This test is only valid on ELF based ports.
#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
# Test Barrier Instruction Operands
.*: *file format .*arm.*
Disassembly of section .text:
00000000 <[^>]*> f3bf 8f5f dmb (sy|#15)
00000004 <[^>]*> f3bf 8f5e dmb (st|#14)
00000008 <[^>]*> f3bf 8f5b dmb (sh|ish|#11)
0000000c <[^>]*> f3bf 8f5b dmb (sh|ish|#11)
00000010 <[^>]*> f3bf 8f5a dmb (ishst|shst|#10)
00000014 <[^>]*> f3bf 8f5a dmb (ishst|shst|#10)
00000018 <[^>]*> f3bf 8f57 dmb (un|nsh|#7)
0000001c <[^>]*> f3bf 8f57 dmb (un|nsh|#7)
00000020 <[^>]*> f3bf 8f56 dmb (unst|nshst|#6)
00000024 <[^>]*> f3bf 8f56 dmb (unst|nshst|#6)
00000028 <[^>]*> f3bf 8f53 dmb (osh|#3)
0000002c <[^>]*> f3bf 8f52 dmb (oshst|#2)
00000030 <[^>]*> f3bf 8f4f dsb (sy|#15)
00000034 <[^>]*> f3bf 8f4e dsb (st|#14)
00000038 <[^>]*> f3bf 8f4b dsb (sh|ish|#11)
0000003c <[^>]*> f3bf 8f4b dsb (sh|ish|#11)
00000040 <[^>]*> f3bf 8f4a dsb (ishst|ish|#10)
00000044 <[^>]*> f3bf 8f4a dsb (ishst|ish|#10)
00000048 <[^>]*> f3bf 8f47 dsb (un|nsh|#7)
0000004c <[^>]*> f3bf 8f47 dsb (un|nsh|#7)
00000050 <[^>]*> f3bf 8f46 dsb (nshst|unst|#6)
00000054 <[^>]*> f3bf 8f46 dsb (nshst|unst|#6)
00000058 <[^>]*> f3bf 8f43 dsb (osh|#3)
0000005c <[^>]*> f3bf 8f6f isb (sy|#15)
00000060 <[^>]*> f3bf 8f6f isb (sy|#15)
00000064 <[^>]*> f3bf 8f5f dmb (sy|#15)
00000068 <[^>]*> f3bf 8f5e dmb (st|#14)
0000006c <[^>]*> f3bf 8f5b dmb (sh|ish|#11)
00000070 <[^>]*> f3bf 8f5b dmb (sh|ish|#11)
00000074 <[^>]*> f3bf 8f5a dmb (ishst|shst|#10)
00000078 <[^>]*> f3bf 8f5a dmb (ishst|shst|#10)
0000007c <[^>]*> f3bf 8f57 dmb (un|nsh|#7)
00000080 <[^>]*> f3bf 8f57 dmb (un|nsh|#7)
00000084 <[^>]*> f3bf 8f56 dmb (unst|nshst|#6)
00000088 <[^>]*> f3bf 8f56 dmb (unst|nshst|#6)
0000008c <[^>]*> f3bf 8f53 dmb (osh|#3)
00000090 <[^>]*> f3bf 8f52 dmb (oshst|#2)
00000094 <[^>]*> f3bf 8f4f dsb (sy|#15)
00000098 <[^>]*> f3bf 8f4e dsb (st|#14)
0000009c <[^>]*> f3bf 8f4b dsb (sh|ish|#11)
000000a0 <[^>]*> f3bf 8f4b dsb (sh|ish|#11)
000000a4 <[^>]*> f3bf 8f4a dsb (ishst|ish|#10)
000000a8 <[^>]*> f3bf 8f4a dsb (ishst|ish|#10)
000000ac <[^>]*> f3bf 8f47 dsb (un|nsh|#7)
000000b0 <[^>]*> f3bf 8f47 dsb (un|nsh|#7)
000000b4 <[^>]*> f3bf 8f46 dsb (nshst|unst|#6)
000000b8 <[^>]*> f3bf 8f46 dsb (nshst|unst|#6)
000000bc <[^>]*> f3bf 8f43 dsb (osh|#3)
000000c0 <[^>]*> f3bf 8f6f isb (sy|#15)
000000c4 <[^>]*> f3bf 8f40 dsb #0
000000c8 <[^>]*> f3bf 8f4f dsb (sy|#15)
000000cc <[^>]*> f3bf 8f50 dmb #0
000000d0 <[^>]*> f3bf 8f5f dmb (sy|#15)
000000d4 <[^>]*> f3bf 8f60 isb #0
000000d8 <[^>]*> f3bf 8f6e isb #14
000000dc <[^>]*> f3bf 8f6b isb #11
000000e0 <[^>]*> f3bf 8f6a isb #10
000000e4 <[^>]*> f3bf 8f67 isb #7
000000e8 <[^>]*> f3bf 8f66 isb #6
000000ec <[^>]*> f3bf 8f63 isb #3
000000f0 <[^>]*> f3bf 8f62 isb #2
000000f4 <[^>]*> f3bf 8f6f isb (sy|#15)

View File

@ -0,0 +1,74 @@
@ Test case to validate barrier instruction operands for T2
.thumb
.section .text
.syntax unified
@Tests to verify dsb, dmb and isb operand acceptance
dmb sy
dmb st
dmb ish
dmb sh
dmb ishst
dmb shst
dmb nsh
dmb un
dmb nshst
dmb unst
dmb osh
dmb oshst
dsb sy
dsb st
dsb ish
dsb sh
dsb ishst
dsb shst
dsb nsh
dsb un
dsb nshst
dsb unst
dsb osh
isb sy
isb
@Sanity checks for operands in upper case
dmb SY
dmb ST
dmb ISH
dmb SH
dmb ISHST
dmb SHST
dmb NSH
dmb UN
dmb NSHST
dmb UNST
dmb OSH
dmb OSHST
dsb SY
dsb ST
dsb ISH
dsb SH
dsb ISHST
dsb SHST
dsb NSH
dsb UN
dsb NSHST
dsb UNST
dsb OSH
isb SY
@Tests to verify immediate operands
dsb 0
dsb #15
dmb 0
dmb #15
isb 0
isb #14
isb #11
isb #10
isb #7
isb #6
isb #3
isb #2
isb #15

View File

@ -0,0 +1,73 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: Barrier Instruction Operands
#as: -mcpu=cortex-a8
# This test is only valid on ELF based ports.
#not-target: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd
# Test Barrier Instruction Operands
.*: *file format .*arm.*
Disassembly of section .text:
00000000 <[^>]*> f57ff05f dmb (sy|#15)
00000004 <[^>]*> f57ff05e dmb (st|#14)
00000008 <[^>]*> f57ff05b dmb (sh|ish|#11)
0000000c <[^>]*> f57ff05b dmb (sh|ish|#11)
00000010 <[^>]*> f57ff05a dmb (ishst|shst|#10)
00000014 <[^>]*> f57ff05a dmb (ishst|shst|#10)
00000018 <[^>]*> f57ff057 dmb (un|nsh|#7)
0000001c <[^>]*> f57ff057 dmb (un|nsh|#7)
00000020 <[^>]*> f57ff056 dmb (unst|nshst|#6)
00000024 <[^>]*> f57ff056 dmb (unst|nshst|#6)
00000028 <[^>]*> f57ff053 dmb (osh|#3)
0000002c <[^>]*> f57ff052 dmb (oshst|#2)
00000030 <[^>]*> f57ff04f dsb (sy|#15)
00000034 <[^>]*> f57ff04e dsb (st|#14)
00000038 <[^>]*> f57ff04b dsb (sh|ish|#11)
0000003c <[^>]*> f57ff04b dsb (sh|ish|#11)
00000040 <[^>]*> f57ff04a dsb (ishst|ish|#10)
00000044 <[^>]*> f57ff04a dsb (ishst|ish|#10)
00000048 <[^>]*> f57ff047 dsb (un|nsh|#7)
0000004c <[^>]*> f57ff047 dsb (un|nsh|#7)
00000050 <[^>]*> f57ff046 dsb (nshst|unst|#6)
00000054 <[^>]*> f57ff046 dsb (nshst|unst|#6)
00000058 <[^>]*> f57ff043 dsb (osh|#3)
0000005c <[^>]*> f57ff06f isb (sy|#15)
00000060 <[^>]*> f57ff06f isb (sy|#15)
00000064 <[^>]*> f57ff05f dmb (sy|#15)
00000068 <[^>]*> f57ff05e dmb (st|#14)
0000006c <[^>]*> f57ff05b dmb (sh|ish|#11)
00000070 <[^>]*> f57ff05b dmb (sh|ish|#11)
00000074 <[^>]*> f57ff05a dmb (ishst|shst|#10)
00000078 <[^>]*> f57ff05a dmb (ishst|shst|#10)
0000007c <[^>]*> f57ff057 dmb (un|nsh|#7)
00000080 <[^>]*> f57ff057 dmb (un|nsh|#7)
00000084 <[^>]*> f57ff056 dmb (unst|nshst|#6)
00000088 <[^>]*> f57ff056 dmb (unst|nshst|#6)
0000008c <[^>]*> f57ff053 dmb (osh|#3)
00000090 <[^>]*> f57ff052 dmb (oshst|#2)
00000094 <[^>]*> f57ff04f dsb (sy|#15)
00000098 <[^>]*> f57ff04e dsb (st|#14)
0000009c <[^>]*> f57ff04b dsb (sh|ish|#11)
000000a0 <[^>]*> f57ff04b dsb (sh|ish|#11)
000000a4 <[^>]*> f57ff04a dsb (ishst|ish|#10)
000000a8 <[^>]*> f57ff04a dsb (ishst|ish|#10)
000000ac <[^>]*> f57ff047 dsb (un|nsh|#7)
000000b0 <[^>]*> f57ff047 dsb (un|nsh|#7)
000000b4 <[^>]*> f57ff046 dsb (nshst|unst|#6)
000000b8 <[^>]*> f57ff046 dsb (nshst|unst|#6)
000000bc <[^>]*> f57ff043 dsb (osh|#3)
000000c0 <[^>]*> f57ff06f isb (sy|#15)
000000c4 <[^>]*> f57ff040 dsb #0
000000c8 <[^>]*> f57ff04f dsb (sy|#15)
000000cc <[^>]*> f57ff050 dmb #0
000000d0 <[^>]*> f57ff05f dmb (sy|#15)
000000d4 <[^>]*> f57ff060 isb #0
000000d8 <[^>]*> f57ff06e isb #14
000000dc <[^>]*> f57ff06b isb #11
000000e0 <[^>]*> f57ff06a isb #10
000000e4 <[^>]*> f57ff067 isb #7
000000e8 <[^>]*> f57ff066 isb #6
000000ec <[^>]*> f57ff063 isb #3
000000f0 <[^>]*> f57ff062 isb #2
000000f4 <[^>]*> f57ff06f isb (sy|#15)

View File

@ -0,0 +1,74 @@
@ Test case to validate barrier instruction operands
.section .text
.syntax unified
@Tests to verify dsb, dmb and isb operand acceptance
dmb sy
dmb st
dmb ish
dmb sh
dmb ishst
dmb shst
dmb nsh
dmb un
dmb nshst
dmb unst
dmb osh
dmb oshst
dsb sy
dsb st
dsb ish
dsb sh
dsb ishst
dsb shst
dsb nsh
dsb un
dsb nshst
dsb unst
dsb osh
isb sy
isb
@Sanity checks for operands in upper case
dmb SY
dmb ST
dmb ISH
dmb SH
dmb ISHST
dmb SHST
dmb NSH
dmb UN
dmb NSHST
dmb UNST
dmb OSH
dmb OSHST
dsb SY
dsb ST
dsb ISH
dsb SH
dsb ISHST
dsb SHST
dsb NSH
dsb UN
dsb NSHST
dsb UNST
dsb OSH
isb SY
@Tests to verify immediate operands
dsb 0
dsb #15
dmb 0
dmb #15
isb 0
isb #14
isb #11
isb #10
isb #7
isb #6
isb #3
isb #2
isb #15

View File

@ -1,3 +1,9 @@
2010-07-08 Tejas Belagod <tejas.belagod@arm.com>
* arm-dis.c (print_insn_arm): Add cases for printing more
symbolic operands.
(print_insn_thumb32): Likewise.
2010-07-06 Maciej W. Rozycki <macro@codesourcery.com>
* mips-dis.c (print_insn_mips): Correct branch instruction type

View File

@ -3155,15 +3155,32 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'U':
switch (given & 0xf)
if ((given & 0xf0) == 0x60)
{
case 0xf: func (stream, "sy"); break;
case 0x7: func (stream, "un"); break;
case 0xe: func (stream, "st"); break;
case 0x6: func (stream, "unst"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
switch (given & 0xf)
{
case 0xf: func (stream, "sy"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
}
}
else
{
switch (given & 0xf)
{
case 0xf: func (stream, "sy"); break;
case 0x7: func (stream, "un"); break;
case 0xe: func (stream, "st"); break;
case 0x6: func (stream, "unst"); break;
case 0xb: func (stream, "ish"); break;
case 0xa: func (stream, "ishst"); break;
case 0x3: func (stream, "osh"); break;
case 0x2: func (stream, "oshst"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
}
}
break;
@ -3998,16 +4015,33 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'U':
switch (given & 0xf)
if ((given & 0xf0) == 0x60)
{
case 0xf: func (stream, "sy"); break;
case 0x7: func (stream, "un"); break;
case 0xe: func (stream, "st"); break;
case 0x6: func (stream, "unst"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
switch (given & 0xf)
{
case 0xf: func (stream, "sy"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
}
}
else
{
switch (given & 0xf)
{
case 0xf: func (stream, "sy"); break;
case 0x7: func (stream, "un"); break;
case 0xe: func (stream, "st"); break;
case 0x6: func (stream, "unst"); break;
case 0xb: func (stream, "ish"); break;
case 0xa: func (stream, "ishst"); break;
case 0x3: func (stream, "osh"); break;
case 0x2: func (stream, "oshst"); break;
default:
func (stream, "#%d", (int) given & 0xf);
break;
}
}
break;
case 'C':